设计模式之桥接模式
【定义】桥接模式(Bridge),将抽象部分与它的实现部分分离,使他们都可以独立地变化。
【场景】继承实际上是一种非常紧密的依赖关系,也即父类实现中的任何变化都将会导致子类发生变化。以手机为例,手机包括品牌和操作系统,假设现在手机品牌分三种:三星,苹果,诺基亚,而手机软件按系统来分也有两种:安卓,IOS。假设一个品牌和一个系统就可以组成一个手机。
首先,手机肯定是一个抽象的对象,按品牌来分可以有三星手机,苹果手机,诺基亚手机,这三种手机是手机抽象对象的三个具体实现,看下面的UML图。实际上操作系统也应该是一个抽象对象,也就应该有一个OperateSystem的对象,而Android和IOS都是从OperateSystem继承过来的具体实现。但下面(UML中)的Android和IOS的父类却是品牌的一个具体实现(父类是Iphone或其它2个),即操作系统的实现是基于品牌的实现的。这样有什么弊端呢?如果现在需要增加一个Symbian的系统,需要做哪些重复的改动?这就是让一个实现基于另外一个实现的局限性。像这种情况最好不要使用类继承,而是使用合成/聚合复用原则。
【UML】更好的设计应该是像下图这样,这样如果需要添加一个Symbian系统只需新增OperateSystem的一个新实现即可。
【代码】
#include <iostream> using namespace std; class OperateSystem { public: virtual void display() = 0; }; class Ios : public OperateSystem { public: void display() { cout<<"IOS"<<endl; } }; class Android : public OperateSystem { public: void display() { cout<<"Android"<<endl; } }; class Phone { protected: OperateSystem* operateSystem; public: virtual void display() = 0; void set_os(OperateSystem* os) { operateSystem = os; } }; class Iphone : public Phone { public: void display() { cout<<"Iphone:\t"; operateSystem->display(); } }; class Nokia : public Phone { public: void display() { cout<<"Nokia:\t"; operateSystem->display(); } }; class Sumsung : public Phone { public: void display() { cout<<"Sumsung: "; operateSystem->display(); } }; int main() { Phone* p1 = new Iphone; Phone* p2 = new Nokia; OperateSystem* os1 = new Ios; OperateSystem* os2 = new Android; p1->set_os(os1); p2->set_os(os2); p1->display(); p2->display(); delete p1; delete p2; delete os1; delete os2; return 0; }【运行结果】
不积跬步无以至千里,不积小流无以成江河。