适配器(Adapter)与外观(Facade)模式
一、问题的提出
假设已有一个软件系统,你希望它能和一个新的厂商类库搭配使用,但是这个新厂商所设计出来的接口不同于旧厂商的接口(但是都能实现需要的功能),这个时候就需要写一个类,将新厂商的接口转换成你所期望的接口。这个类的对象就是 对象适配器。
二、实例说明
下面用一个实例说明适配器的工作。有一个火鸡类Turkey,现在需要将它用适配器包装起来,使他变成“鸭子”。
头文件:#ifndef ADAPTER__H #define ADAPTER__H #include <iostream> using namespace std; //定义鸭子抽象类Duck,具有叫和飞的能力 class Duck { public: virtual void quack() = 0; virtual void fly() = 0; }; //定义MallardDuck类,它是鸭子的子类 class MallardDuck : public Duck { public: void quack(); void fly(); }; //定义火鸡抽象类Turkey,具有gobble叫和短途飞行能力 class Turkey { public: virtual void gobble() = 0; virtual void shortFly() = 0; }; //定义WildTurkey类,它是火鸡类Turkey的具体实例 class WildTurkey : public Turkey { public: void gobble(); void shortFly(); }; //适配器类.将火鸡转换成鸭子的适配器. //需要实现想转换成的类型接口,也就是客户所期望看到的接口(此例子中Duck是期望的接口) class TurkeyAdapter : public Duck { public: Turkey* turkey; TurkeyAdapter(Turkey* turkey);//取得要适配的对象的引用或指针,这里我们使用构造器取得 void quack();//实现接口中的所有方法,quack()在类之间的转换很简单,只要调用gobble()就可以 void fly(); }; #endif
cpp:#include "Adapter.h" void MallardDuck::quack() { cout<<"Quack"<<endl; } void MallardDuck::fly() { cout<<"I'm flying"<<endl; } void WildTurkey::gobble() { cout<<"Gobble gobble"<<endl; } void WildTurkey::shortFly() { cout<<"I'm flying a short distance"<<endl; } TurkeyAdapter::TurkeyAdapter(Turkey *turkey) { this->turkey = turkey; } void TurkeyAdapter::fly() { for(int i=0; i<3; ++i) this->turkey->shortFly(); } void TurkeyAdapter::quack() { this->turkey->gobble(); }
测试用例:#include "Adapter.h" void testDuck(Duck* duck) { duck->quack(); duck->fly(); } int main() { MallardDuck* duck = new MallardDuck();//创建鸭子 WildTurkey* turkey = new WildTurkey();//创建火鸡 Duck* turkeyAdapter = new TurkeyAdapter(turkey);//将火鸡包装进一个火鸡适配器中,这样它就“成了”鸭子 testDuck(duck);//测试鸭子 cout<<endl; testDuck(turkeyAdapter);//测试假装是鸭子的火鸡适配器 delete duck; delete turkey; delete turkeyAdapter; getchar(); }
三、定义适配器模式
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
四、外观模式
外观模式比较容易理解,比较实用。外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。