• 设计模式——适配器模式(Adapter Pattern)


    解决的问题:

    适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。比如说我的hp笔记本,美国产品,人家美国的电压是110V的,而我们中国的电压是220V,要在中国能使用,必须找个变压器转一下电压才可以。这个变压器就是个适配器。

    适配器模式有类适配器和对象适配器两种模式,我们将分别讨论。


    类适配器:

    由图中可以看出,Adaptee类没有Request方法,而客户期待这个方法。为了使客户能够使用Adaptee类,提供一个中间环节,即类Adapter类,Adapter类实现了Target接口,并继承自AdapteeAdapter类的Request方法重新封装了AdapteeSpecificRequest方法,实现了适配的目的。

    因为AdapterAdaptee是继承的关系,所以这决定了这个适配器模式是类的。

    该适配器模式所涉及的角色包括:

    目标(Target)角色:这是客户所期待的接口。因为C#不支持多继承,所以Target必须是接口,不可以是类。
    源(Adaptee)角色:需要适配的类。
    适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类

        简单实现:

    1. #include<iostream>  
    2. using namespace std;  
    3.   
    4. // "ITarget"  
    5. class Target  
    6. {  
    7. public:  
    8.     // Methods  
    9.     virtual void Request(){};  
    10. };  
    11.   
    12. // "Adaptee"  
    13. class Adaptee  
    14. {  
    15. public:  
    16.     // Methods  
    17.     void SpecificRequest()  
    18.     {  
    19.         cout<<"Called SpecificRequest()"<<endl;  
    20.     }  
    21. };  
    22.   
    23. // "Adapter"  
    24. class Adapter : public Adaptee, public Target  
    25. {  
    26. public:  
    27.     // Implements ITarget interface  
    28.     void Request()  
    29.     {  
    30.         // Possibly do some data manipulation  
    31.         // and then call SpecificRequest    
    32.         this->SpecificRequest();  
    33.     }  
    34. };  
    35.   
    36.   
    37. int main()  
    38. {  
    39.     // Create adapter and place a request  
    40.     Target *t = new Adapter();  
    41.     t->Request();  
    42.   
    43.     return 0;  
    44. }  

    对象适配器:

    从图中可以看出:客户端需要调用Request方法,而Adaptee没有该方法,为了使客户端能够使用Adaptee类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装了一个Adaptee的实例,从而将客户端与Adaptee衔接起来。由于AdapterAdaptee是委派关系,这决定了这个适配器模式是对象的。

    该适配器模式所涉及的角色包括:

    目标(Target)角色:这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
    源(Adaptee)角色:需要适配的类。
    适配器(Adapter)角色:通过在内部包装(Wrap)一个Adaptee对象,把源接口转换成目标接口。

    简单实现:

    1. #include<iostream>  
    2. using namespace std;  
    3.   
    4. // "ITarget"  
    5. class Target  
    6. {  
    7. public:  
    8.     // Methods  
    9.     virtual void Request(){};  
    10. };  
    11.   
    12. // "Adaptee"  
    13. class Adaptee  
    14. {  
    15. public:  
    16.     // Methods  
    17.     void SpecificRequest()  
    18.     {  
    19.         cout<<"Called SpecificRequest()"<<endl;  
    20.     }  
    21. };  
    22.   
    23. // "Adapter"  
    24. class Adapter : public Target  
    25. {  
    26. private:  
    27.     Adaptee *adaptee;  
    28.   
    29. public:  
    30.     Adapter()  
    31.     {  
    32.         adaptee = new Adaptee();  
    33.     }  
    34.   
    35.     // Implements ITarget interface  
    36.     void Request()  
    37.     {  
    38.         // Possibly do some data manipulation  
    39.         // and then call SpecificRequest    
    40.         adaptee->SpecificRequest();  
    41.     }  
    42. };  
    43.   
    44.   
    45. int main()  
    46. {  
    47.     // Create adapter and place a request  
    48.     Target *t = new Adapter();  
    49.     t->Request();  
    50.   
    51.     return 0;  
    52. }  

    缺省适配器:

    缺省适配器模式是一种特殊的适配器模式,但这个适配器是由一个抽象类实现的,并且在抽象类中要实现目标接口中所规定的所有方法,但很多方法的实现都是平庸的实现,也就是说,这些方法都是空方法。而具体的子类都要继承此抽象类。 

    简单实现:

    1. #include<iostream>  
    2. using namespace std;  
    3.   
    4.   
    5. class Target {   
    6. public:  
    7.     virtual void f1(){};   
    8.     virtual void f2(){};   
    9.     virtual void f3(){};     
    10. };  
    11.   
    12. class DefaultAdapter : public Target   
    13. {   
    14. public:  
    15.     void f1() {   
    16.     }   
    17.   
    18.     void f2() {   
    19.     }   
    20.   
    21.     void f3() {   
    22.     }   
    23. };  
    24.   
    25. class MyInteresting :public DefaultAdapter  
    26. {   
    27. public:  
    28.      void f3(){         
    29.         cout<<"呵呵,我就对f3()方法感兴趣,别的不管了!"<<endl;  
    30.     }   
    31. };  
    32.   
    33. int main()  
    34. {  
    35.     // Create adapter and place a request  
    36.     Target *t = new MyInteresting();  
    37.     t->f3();  
    38.   
    39.     return 0;  
    40. }  


    实现要点:

    1.Adapter模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,在遗留代码复用、类库迁移等方面非常有用

    2Adapter模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用多继承的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用对象组合的方式,更符合松耦合精神。

    3Adapter模式的实现可以非常的灵活,不必拘泥于GOF23中定义的两种结构。例如,完全可以将Adapter模式中的现存对象作为新的接口方法参数,来达到适配的目的。

    4Adapter模式本身要求我们尽可能地使用面向接口的编程风格,这样才能在后期很方便的适配


    使用场景:

    在以下各种情况下使用适配器模式:

    1.系统需要使用现有的类,而此类的接口不符合系统的需要。

    2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。

    3.(对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。


  • 相关阅读:
    Spire.Barcode好用的条码生在组件
    jQuery、js操作页面
    设计模式---简介
    设计模式---策略设计模式
    POI生成Excel文件:Excel,工具类,背景色,边框,居中,合并单元格
    设计模式---模板设计模式(java)
    maven打包不打lib目录里面的jar包解决办法
    MySQL库表操作
    Linux环境根据data目录文件恢复MySQL数据
    Linux 安装 mysql 与 mysql在Linux环境本地使用,但windows远程连不了问题处理
  • 原文地址:https://www.cnblogs.com/nktblog/p/4027098.html
Copyright © 2020-2023  润新知