1、为什么要用适配器模式?
假设有一个目标抽象类,其中定义了某个客户想要使用的方法(只是定义,没有实现);这时候有另一个类,我们称之为适配者类,其中包含了一些具体的已经实现的方法;由于目标抽象类中定义的方法名称和客户想要真正调用的方法名称不一样,但是我们为了原有系统的稳定性,不想更改目标抽象类,而且适配者类中方法可能源代码我们都看不到,无法更改,这个时候就需要一个中间类,在这个中间类中去实现目标抽象类的方法,但是这个方法的底层却是调用适配者类中实现的方法,这样就满足了客户既不用更改原有的代码同时可以调用适配者类中实现的方法的目的。
2、怎么用适配器模式?
适配器模式主要有四种用法,分别为类适配器模式,对象适配器模式,缺省适配器模式,双向适配器模式。
1)类适配器模式
类适配器模式和对象适配器模式的功能相同,用法不同,但由于类适配器模式中适配者类一般为具体类,由于c#不支持多重继承,要想实现多重继承必须要使用接口,故类适配器模式一般只能适配一个适配者类。
目标抽象类:
interface Target
{
void Request();
}
适配者类:
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("我是一个适配者类");
}
}
适配器类:
class Adapter:Adaptee ,Target
{
public void Request()
{
base.SpecificRequest();
}
}
调用代码:
public Form1()
{
InitializeComponent();
Adapter adapter = new Adapter();
adapter.Request();
}
2)对象适配器
对象适配器相对于类适配器只是更改了适配器类以及客户端调用的方式,对象适配器可以解决类适配器无法适配多个适配者的问题,分别如下:
class Adapter:Target
{
public Adaptee adaptee;
public Adapter (Adaptee adaptee)
{
this.adaptee = adaptee;
}
public void Request()
{
adaptee.SpecificRequest();
}
}
public Form1()
{
InitializeComponent();
Adaptee adaptee = new Adaptee();
Adapter adapter = new Adapter(adaptee );
adapter.Request();
}
3)缺省适配器(单接口适配器模式)
当有一个适配者类含有很多个方法,但是我们不是每次都需要将方法全部实现时,我们可以设计一个适配者接口,然后用一个抽象类去实现这个适配者接口中的方法,并提供空的实现,同时将这些空实现标记为virtural,这样我们具体类想实现哪个方法,直接覆盖这个空实现就好了(这种情况适用于我们知道适配者类原代码的情况),代码如下:
包含多个方法定义的适配者接口
interface Adaptee
{
void Request1();
void Request2();
void Request3();
}
抽象适配者类:
abstract class AbstractAdaptee:Adaptee
{
public virtual void Request1()
{
}
public virtual void Request2()
{
}
public virtual void Request3()
{
}
}
具体适配者类
class ConcreteAdaptee : AbstractAdaptee
{
public override void Request1()
{
Console.WriteLine("我是具体目标类方法1");
}
}
目标接口
interface Target
{
void Request();
}
适配器类
class Adapter:Target
{
public Adaptee adaptee;
public Adapter(Adaptee adaptee)
{
this.adaptee = adaptee;
}
public void Request()
{
adaptee.Request1();
}
}
客户端调用
public Form1()
{
InitializeComponent();
Adaptee adaptee = new ConcreteAdaptee();
Adapter adapter = new Adapter(adaptee);
adapter.Request();
}
4)双向适配器
双向适配器也就是适配器类中包含了对目标类、适配者类的引用,适配者类可以调用目标类中的方法,目标类也可以调用适配者类中方法。
Cat作为目标类
interface Cat
{
void CatchMouse();
}
class ConcreteCat:Cat
{
public void CatchMouse()
{
Console.WriteLine("我是猫,我会抓老鼠");
}
}
dog作为适配者类
interface Dog
{
void Cry();
}
class ConcreteDog:Dog
{
public void Cry()
{
Console.WriteLine("我是狗,我会叫");
}
}
class Adapter : Dog,Cat
{
private Cat cat;
private Dog dog;
public Adapter(Cat cat)
{
this.cat = cat;
}
public Adapter(Dog dog)
{
this.dog = dog;
}
public void Cry()
{
cat.CatchMouse();
}
public void CatchMouse()
{
dog.Cry();
}
}
客户端调用(Cat可以调用dog的cry方法,dog也可以调用cat的catchmouse)
public Form1()
{
InitializeComponent();
Dog dog = new ConcreteDog();
Adapter adapterDog = new Adapter(dog);
adapterDog.CatchMouse();//适配器中的适配者对象调用目标类定义的CatchMouse方法
Cat cat = new ConcreteCat();
Adapter adapterCat = new Adapter(cat);
adapterCat.Cry();//适配器中的目标对象调用适配者类定义的Cry方法
}