一、适配器模式
1.将一个类的接口转换成客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2.在一个新的项目中,一些所需要的类在旧的项目中就已经存在,但是由于接口的不同导致已有的类无法被复用,而由于项目时间比较紧又无法改造已有的类,这个时候就应该想办法来“适配”已有的类。
3.系统或模块的数据和处理流程都是正确的,但是接口与新系统不符时,我们就应该考虑使用适配器模式以达到可控范围之外的对象和某个接口相匹配。当需要复用一些现存的类但是其接口与复用接口环境不一致时,适配器模式拥有很高的价值。
举例:
class Target //客户期望的接口
{
public virtual void Request() //客户的基本请求
{
Console.WriteLine("客户的基本请求");
}
}
class Adaptee //需要被适配的类
{
public void SpecificRequest() //客户的特殊请求
{
Console.WriteLine("客户的特殊请求");
}
}
class Adapter:Target //适配器类
{
//包含一个私有的Adaptee对象,所以本类为适配器
private Adaptee adaptee = new Adaptee();
//覆盖基类的Request方法
public override void Request(){
adaptee.SpecificRequest();
}
}
适配器模式分为类适配器和对象适配器,两者的分别如下:
1.对象适配器:不是通过继承方式,而是通过对象组合的方式来讲进行处理。
2.类适配器:通过继承的方式来实现,将旧系统的方法进行封装。对象适配器在进行适配器之间转换过程中,无疑使用类适配器也能完成,但是依赖性会变大,并且根据适配要求的灵活性,可能通过继承系统会膨胀到难以控制。
二、桥接模式
将抽象的部分与它的实现部分分离,从效果上来说,解除了不同分类的实现之间的耦合性使他们可以独立的变化。
1.当不希望在抽象和他的实现部分有一个固定的绑定关系。
2.当类的抽象以及他的实现都应该可以通过生成子类的方法加以扩充时。
3.当对一个抽象类的实现部分的修改应对客户不产生影响时(客户的代码不需要重新编译)。
/*******************抽象类**************************/
abstract class Implementor
{
public abstract void Operation();
}
abstract class Abstraction
{
protected Implementor implementor;
public void SetImplementor(Implementor implementor)
{
this.implementor = implementor;
}
public abstract void Operation();
}
/****************继承抽象类*********************/
class ConcreteImplementorA : Implementor
{
public override void Operation()
{
Console.WriteLine("A的具体操作");
}
}
class ConcreteImplementorB : Implementor
{
public override void Operation()
{
Console.WriteLine("B的具体操作");
}
}
class RedefineAbstraction : Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
/******************举例执行********************/
static void Main(string[] args)
{
Abstraction abstraction = new RedefineAbstraction();
abstraction.SetImplementor(new ConcreteImplementorA());
abstraction.Operation();
abstraction.SetImplementor(new ConcreteImplementorB());
abstraction.Operation();
}
在编程过程中进行抽象的方法一般就是创建一个类的层次结构,在这其中,抽象类就处在这个层次结构的顶端位置,它的作用就是定义好一些抽象的操作集合,在这个层次结构中每一个子类 实际上都是抽象操作集合的不同实现方式,但是当需要对这个层次结构做子类化操作时,就会遇到各种各样的问题。通过将前面提到的抽象操作的集合转移到一个接口中,就可以创建一个所谓的桥,这样做的好处就是使我们想要的抽象取决于对这个接口的实现,而桥接模式的目的正是将一个抽象和其它抽象操作的实际分离,这样一来,抽象和其他的抽象操作的就可以独立的进行改变了。 某个抽象是一个类,那么它必将依赖于抽象方法。前面提到的抽象的层次就是最简单的抽象的例子,在这种方式下,父类中具体方法就必然依赖于其他的抽象方法。 当我们遵循原有的层次结构按照另外一种方向继续派生子类的时候,我们就不得不将这些抽象方法也一并移植到其他的层次结构当中去,这时就可以使用桥接模式了,从而将一个抽象于这个抽象中所提供的抽象方法的实现互相分离。
三 建造者模式
建造者模式可以说是对流程的抽象,当创建复杂对象的算法应该独立于该对象的组成部分以及它们的组装方式的情况下,适合使用建造者模式。
class Product{
List<string>parts = new List<string>();
public void Add(string part){
parts.Add(part);
}
public void Show(){
Console.WriteLine("Create Product");
for(int i =0 ;i < parts.Count;++i){
Console.WriteLine(parts[i]);
}
}
}
abstract class Builder{
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract Product GetResult();
}
class ConcreteBuilderA:Builder{
private Product product = new product();
public override void BuilderPartA(){
product.Add("Part A");
}
public override void BuilderPartB(){
product.Add("Part B");
}
public override Product GetResult(){
return product;
}
}
class ConcreteBuilderB:Builder{
private Product product = new product();
public override void BuilderPartA(){
product.Add("Part W");
}
public override void BuilderPartB(){
product.Add("Part Z");
}
public override Product GetResult(){
return product;
}
}
class Director{
public void Construct(Builder builder){
builder.BuilderPartA();
builder.BuilderPartB();
}
}
static void Main(string[] args){
Director director = new Director();
Builder builderA = new ConcreteBuilderA();
builder builderB = new ConcreteBuilderB();
director.Construct(builderA);
Product productA = builderA.GetResult();
productA.Show();
director.Construct(builderB);
Product productB = builderB.GetResult();
productB.Show();
}
在一些项目中,经常需要构建一些比较复杂的对象,并对其多个属性进行赋值的复杂操作,程序员的一些忽略可能导致某个属性未被赋值,而引起对象的失效,在这种情况下使用构造者模式,创建一个Director来按部就班地指挥一个对象的创建,可以有效的避免意外的发生。使用创建者模式,用户只需要指定创建的类型就可以得到相应的对象,而具体的建造过程和细节就被Director和Builder隐藏了,这正是依赖倒转的体现:抽象不应该依赖于细节,细节应该依赖于抽象。