本文共 3544 字,大约阅读时间需要 11 分钟。
原文地址:
Bridge模式: Bridge模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。这并不是说,让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。比如手机既可以按照品牌来分类,也可以按照功能来分类。再通俗点“将抽象部分与它的实现部分分离”就是现实系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合。
这里引用《大话设计模式》中对于Bridge模式描述的手机游戏的例子:如果要实现一个N品牌的手机游戏,就提供一个此品牌的游戏类HandsetNGame。此时,如果再来一个M品牌的手机游戏,就提供一个HandsetMGame,并提取一个HandsetGame作为两个品牌手机游戏的基类。然后手机都需要通讯录功能,现在就有点麻烦了,父类应该是“手机品牌”,下面有“手机品牌M”和“手机品牌N”,每个品牌下各自有“通讯录”和“游戏”子类。 代码结构图如下: 1手机品牌 2手机品牌M 3手机品牌M通讯录 3手机品牌M游戏 2手机品牌N 3手机品牌N通讯录 3手机品牌N游戏
此时如果再来个MP3,就得在没个品牌下面增加一个MP3类。再来一个新品牌S,就得再增加“手机品牌S”和三个子类。如果再添加“输入法”、“拍照”…,再增加L品牌,X品牌,那类就呈爆炸性增长了。 或许可以换一种方式分类: 1手机软件 2通讯录 3手机品牌M通讯录 3手机品牌N通讯录 2游戏 3手机品牌M游戏 3手机品牌N游戏 但同样如果再来个新品牌S,再来个“输入法”,仍然得添加“手机品牌S”和“手机品牌S通讯录”,“手机品牌S游戏”,“手机品牌S输入法”。
上面两个单独的分类方式都没法解决类的膨胀。
先回顾下CARP(Composite/Aggregate Reuse Principle)原则:尽量使用组合/聚合,尽量不要使用类继承。 实际上,“游戏”、“通讯录”、“MP3”都是软件,不同的厂商生产不同的品牌。如果有个“手机品牌”抽象类,不同的品牌都继承于它;有个“手机软件”抽象类,不同的功能软件都继承于它。那么要增加新的品牌或者新的功能软件就不影响对方了。 即: 1手机品牌 2手机品牌M 2手机品牌N
1手机软件 2通讯录 2游戏
然后考虑下“手机品牌”和“手机软件”之间应该是什么关系呢?应该是手机品牌包含有手机软件,但软件并不是品牌的一部分,所以他们之间应该是聚合关系。
Bridge模式典型的结构图为:
//Abstraction.h#ifndef _ABSTRACTION_H_#define _ABSTRACTION_H_class HandsetSoft;// 手机品牌class HandsetBrand{public: virtual ~HandsetBrand(); virtual void Operation() = 0;protected: HandsetBrand();private:};// 手机品牌Mclass HandsetBrandM : public HandsetBrand{public: HandsetBrandM(HandsetSoft* imp); ~HandsetBrandM(); void Operation();protected:private: HandsetSoft* _imp;};// 手机品牌Nclass HandsetBrandN : public HandsetBrand{public: HandsetBrandN(HandsetSoft* imp); ~HandsetBrandN(); void Operation();protected:private: HandsetSoft* _imp;};#endif //~_ABSTRACTION_H_//Abstraction.cpp#include "Abstraction.h"#include "AbstractionImp.h"#include与前面的Builder模式相比,Bridge和Builder都抽象出来一个基类,这个基类里面定义了共有的一些行为,形成接口函数;都聚合一个基类的指针,Builder因装配不同部分的过程是一致的,所以封装在构造函数中,Builder封装了不同的生成组成部分的方式,而Bridge封装了不同的实现方式。using namespace std;HandsetBrand::HandsetBrand(){}HandsetBrand::~HandsetBrand(){}HandsetBrandM::HandsetBrandM(HandsetSoft* imp){ _imp = imp;}HandsetBrandM::~HandsetBrandM(){}void HandsetBrandM::Operation(){ _imp->Operation();}HandsetBrandN::HandsetBrandN(HandsetSoft* imp){ _imp = imp;}HandsetBrandN::~HandsetBrandN(){}void HandsetBrandN::Operation(){ _imp->Operation();}//AbstractionImp.h#ifndef _ABSTRACTIONIMP_H_#define _ABSTRACTIONIMP_H_// 手机软件class HandsetSoft{public: virtual ~HandsetSoft(); virtual void Operation() = 0;protected: HandsetSoft();private:};// 手机游戏class HandsetSoftGame : public HandsetSoft{public: HandsetSoftGame(); ~HandsetSoftGame(); virtual void Operation();protected:private:};// 手机通讯录class HandsetSoftAddressList : public HandsetSoft{public: HandsetSoftAddressList(); ~HandsetSoftAddressList(); virtual void Operation();protected:private:};#endif //~_ABSTRACTIONIMP_H_//AbstractionImp.cpp#include "AbstractionImp.h"#include using namespace std;HandsetSoft::HandsetSoft(){}HandsetSoft::~HandsetSoft(){}void HandsetSoft::Operation(){ cout<<"HandsetSoft...操作手机软件..."< using namespace std;int main(int argc,char* argv[]){ HandsetSoft* softg1 = new HandsetSoftGame(); HandsetBrand* brandm1 = new HandsetBrandM(softg1); brandm1->Operation(); HandsetSoft* softa1 = new HandsetSoftAddressList(); HandsetBrand* brandm2 = new HandsetBrandM(softa1); brandm2->Operation(); HandsetSoft* softg2 = new HandsetSoftGame(); HandsetBrand* brandn1 = new HandsetBrandN(softg2); brandn1->Operation(); HandsetSoft* softa2 = new HandsetSoftAddressList(); HandsetBrand* brandn2 = new HandsetBrandN(softa2); brandn2->Operation(); return 0;}