08.桥接模式--Bridge

来源:互联网 发布:美国一年制硕士 知乎 编辑:程序博客网 时间:2024/05/16 08:58

原文地址:http://blog.csdn.net/jjunjoe/article/details/6649591

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模式典型的结构图为:
 

分析到此,下面是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 <iostream>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 <iostream>using namespace std;HandsetSoft::HandsetSoft(){}HandsetSoft::~HandsetSoft(){}void HandsetSoft::Operation(){ cout<<"HandsetSoft...操作手机软件..."<<endl;}HandsetSoftGame::HandsetSoftGame(){}HandsetSoftGame::~HandsetSoftGame(){}void HandsetSoftGame::Operation(){ cout<<"HandsetSoftGame...操作手机游戏..."<<endl;}HandsetSoftAddressList::HandsetSoftAddressList(){}HandsetSoftAddressList::~HandsetSoftAddressList(){}void HandsetSoftAddressList::Operation(){ cout<<"HandsetSoftAddressList...操作手机通讯录..."<<endl;}//main.cpp#include "Abstraction.h"#include "AbstractionImp.h"#include <iostream>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;}
与前面的Builder模式相比,Bridge和Builder都抽象出来一个基类,这个基类里面定义了共有的一些行为,形成接口函数;都聚合一个基类的指针,Builder因装配不同部分的过程是一致的,所以封装在构造函数中,Builder封装了不同的生成组成部分的方式,而Bridge封装了不同的实现方式。

0 0
原创粉丝点击