为方便读者,本文已添加至索引:
Adapter(适配器)模式主要解决接口不匹配的问题。为此,让我们要回到最初Builder模式创建平行世界时,白雪公主和小霍比特人的谜之相遇。在这个世界里,我们暂时有见到两个种族Human和Hobbit。种族不同所产生的最大区别是什么?当然个头是一部分,也仅仅是一部分而已。毕竟Human里也有怎么长都才那么高的吧:P。这里要说的区别是:他们的语言不通。是的,白雪公主一开始根本就听不懂小霍比特人在说什么。
在这个平行世界中,所有的Human通用语是中文,(为什么是中文!因为全世界都在学中国话。)包括白雪公主(你知道我是一定不会忠于原著的)。而霍比特人,我们假定他们用的是霍比特语。所以大家在表达“打招呼”的意思时,用的是完全不同的语言:
class Human {
public:
// … other action …
virtual void hello() { cout << "你好!" << endl; }
}
class Hobbit {
public:
// … other action …
virtual void hohobi() { cout << "HOhoBI*" << endl; }
}
那后来白雪公主又是怎么与小霍比特人们幸福快乐地生活在一起了呢?这里要提的是7个小霍比特人中,有一位博学的老者theWise,他曾在人类社会中生活了大半辈子,他曾任职于『跨种族文化研究协会』Cross-Racial Culture(CRC)。那段难忘的研究经历让他对Human的文化也是相当熟悉:
class CRC: public Human, public Hobbit {
public:
// … other action …
virtual void hohobi() { hello(); }
}
可以看到,CRC其实就是一个适配器,更具体的说,是类适配器。(适配器模式有两种版本:类适配器和对象适配器,下文会讲到)它使用多重继承对一个接口与另一个接口进行匹配,见示例部分的说明。大家可以想想现实生活中,我们是不是还见过许多类似适配器的设计?让我们来看看适配器模式的相关要点。
目的分类
范围准则
主要功能
适用情况
我们想使用一个已经存在的类,而它的接口不符合我们的需求
我们想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口
可能不一定兼容的类)协同工作
参与部分
协作过程
UML图
类适配器
对象适配器
当美丽的白雪公主遇到一个可爱的小霍比特人时,她向他打招呼:
Human theWhitePrincess = new Human();
Hobbit theLovely = new Hobbit();
theWhitePrincess.hello(); //你好!
但是小霍比特人理解不了。在他的世界里,hohobi()才是打招呼的方式。而Human是没有hohobi()的,于是白雪公主沟通陷入了尴尬的状态。好在theWise及时的来了:
Hobbit theWise = new CRC();
theWise.hohobi(); //你好!
于是白雪公主和其他小霍比特人通过theWise都能互相理解了。借用下面这个图我们可以理解下:
跨种族文化研究协会就是为了实现种族之间文化交流沟通没有障碍而生。它在这个场景下,就起到了适配器的作用,通过将Hobbit人打招呼的接口hobbit()转化成Human打招呼的接口hello进行输出。
但是世界的创造者时の魔导士也注意到了这件事。他并不希望以后的日子里,白雪公主都要在theWise的陪同下才能与其他人沟通,太不方便了对不对。于是他采用了童话世界里最常出现的谜之物:霍比特仙果:一个能吃了后能让人类获得理解霍比特人的神奇果实。从本质上来看,吃过果子后,属于新的类别:HumanPlus
class HumanPlus : public Human {
public:
// … other action …
virtual void hello() { _hobbitSprite->hohobi(); }
private:
Hobbit* _hobbitSprite;
}
它的最大特色是,自己维护了一个Hobbit类的指针。利用_hobbitSprite对象达到适配器的目的,这就是另一种对象适配器的模式。让我们来看图:
总之,白雪公主顺利地融入到小霍比特人的生活中。
在此,我们可以总结下类适配器和对象适配器各自的特点:
我们需要注意的一些问题:
今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章