08.桥接模式--Bridge

 

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:
};

// 手机品牌M
class HandsetBrandM : public HandsetBrand
{
public:
 HandsetBrandM(HandsetSoft* imp);
 ~HandsetBrandM();
 void Operation();
protected:
private:
 HandsetSoft* _imp;
};

// 手机品牌N
class 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值