Adapter模式主要意图是将类或接口转换成客户期望的接口,从而使得原本不兼容、无法在一起工作的接口可以在一起工作。该模式有两种形式的Adapter法,一是继承方式;二是对象关联依赖方式。
继承方式Adapter法,相比之下,耦合性更强些,并且毕竟依赖于静态继承,如果被适配的对象有多个(派生)版本的话,则在运行时,将无法做到动态适配,因此,如果想要切换适配对象,就必需要重新编译链接。该方式的类关系参考如下:
就Adapter的目的来说,Adapter对象在使用目的上与被适配的Adaptee对象本质上是没有什么关系的,因此可以说Adapter对象并不是一个Adaptee对象,Adapter对象仅仅只是需要Adaptee对象的相关功能而已(可以直观理解为:借个道,从你这路过而已)。继承方式的Adapter的编码结构参考如下:
1 namespace adapter 2 { 3 class Target 4 { 5 public: 6 virtual void doSomething() {}; 7 // some code here........(like virtual destructor etc.) 8 9 };//class Target 10 11 class Adaptee 12 { 13 public: 14 void doSpecifyWork() { /* some code here........ */ } 15 16 };//class Adaptee 17 18 class Adapter : public Target 19 , private Adaptee 20 { 21 public: 22 virtual void doSomething() override { Adaptee::doSpecifyWork(); } 23 24 }//class Adapter 25 26 }//namespace adapter
前面已述继承式的Adapter相对灵活性不强,而且最重要的问题是耦合性变强了,只要被适配对象有变动就需要重新编译链接。对象关联依赖方式相比继承方式更为灵活,并且可以在运行时对于同一系列的Adaptee进行动态适配。就设计而言,我们总是希望优先使用组合方式而非继承。因此,对于Adapter,建议优先考虑关联依赖式。类关系图参考如下:
模式编码结构参考如下:
1 namespace adapter 2 { 3 class Target 4 { 5 public: 6 virtual void doSomething() {}; 7 // some code here........(like virtual destructor etc.) 8 9 };//class Target 10 11 class Adaptee 12 { 13 public: 14 void doSpecifyWork() { /* some code here........ */ } 15 16 };//class Adaptee 17 18 class Adapter : public Target 19 { 20 public: 21 virtual void doSomething() override { 22 auto pAdaptee = this->getAdaptee(); 23 if (nullptr != pAdaptee) { 24 pAdaptee->doSpecifyWork(); 25 } 26 // some code here........ 27 } 28 // some code here........ 29 30 private: 31 Adaptee* getAdaptee() { return m_pAdaptee; } 32 33 private: 34 Adaptee* m_pAdaptee; 35 36 }//class Adapter 37 38 }//namespace adapter
实际上,Adapter可以提高代码的复用性,可以让多个互不相干的功能模块协同工作。但是Adapter时的难易程度与必要性,有时候也是需要斟酌的。如:待适配的以象极期复杂,而且与期望的对象相似度极低,此时,Adapter就比较蛋碎,肯定会花费不少时间与功夫,此时就需要进一步考虑是否真的有这个必要去适配。即:我们在动手前,需要先分析下Adapter的代价。这个算是一个注意点吧。