Bridge桥接模式

来源:互联网 发布:按摩棒 知乎 编辑:程序博客网 时间:2024/06/06 12:51

将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化。

桥接模式号称设计模式中最难理解的模式之一,关键就是这个抽象和实现的分离非常让人奇怪,大部分人刚看到这个定义的时候都会认为实现就是继承自抽象,那怎么可能将他们分离呢。

《大话设计模式》中就Bridge模式的解释:

手机品牌和软件是两个概念,不同的软件可以在不同的手机上,不同的手机可以有相同的软件,两者都具有很大的变动性。如果我们单独以手机品牌或手机软件为基类来进行继承扩展的话,无疑会使类的数目剧增并且耦合性很高,(如果更改品牌或增加软件都会增加很多的变动)两种方式的结构如下:

 

所以将两者抽象出来两个基类分别是PhoneBrand和PhoneSoft,那么在品牌类中聚合一个软件对象的基类将解决软件和手机扩展混乱的问题,这样两者的扩展就相对灵活,剪短了两者的必要联系,结构图如下:

这样扩展品牌和软件就相对灵活独立,达到解耦的目的!

 UML结构图如下:

抽象基类及接口:

1、Abstraction::Operation():定义要实现的操作接口

2、AbstractionImplement::Operation():实现抽象类Abstaction所定义操作的接口,由其具体派生类ConcreteImplemenA、ConcreteImplemenA或者其他派生类实现。

3、在Abstraction::Operation()中根据不同的指针多态调用AbstractionImplement::Operation()函数。

理解:
Bridge用于将表示和实现解耦,两者可以独立的变化.在Abstraction类中维护一个AbstractionImplement类指针,需要采用不同的实现方式的时候只需要传入不同的AbstractionImplement派生类就可以了. 

桥接模式就将实现与抽象分离开来,使得RefinedAbstraction依赖于抽象的实现,这样实现了依赖倒转原则,而不管左边的抽象如何变化,只要实现方法不变,右边的具体实现就不需要修改,而右边的具体实现方法发生变化,只要接口不变,左边的抽象也不需要修改。

常用的场景
1.当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如上面例子中手机品牌有2种变化因素,一个是品牌,一个是功能。

2.当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来,如上面例子中的通讯录和游戏,其实是可以共享的。

3.当我们考虑一个对象的多个变化因素可以动态变化的时候,考虑使用桥接模式,如上面例子中的手机品牌是变化的,手机的功能也是变化的,所以将他们分离出来,独立的变化。

优点
1.将实现抽离出来,再实现抽象,使得对象的具体实现依赖于抽象,满足了依赖倒转原则。

2.将可以共享的变化部分,抽离出来,减少了代码的重复信息。

3.对象的具体实现可以更加灵活,可以满足多个因素变化的要求。

缺点
1.客户必须知道选择哪一种类型的实现。

    

实际上上面使用Bridge模式和使用带来问题方式的解决方案的根本区别在于是通过继承还是通过组合的方式去实现一个功能需求。设计中有多维的变化我们就可以用桥模式。如果只有一维在变化,那么我们用继承就可以圆满的解决问题。在发现需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放-封闭原则时,就要考虑用Bridge桥接模式了。

合成/聚合复用原则:   

1、 尽量使用合成/聚合,尽量不要使用类继承。
2、优先使用对象的合成/聚合将有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。


 代码如下: 



#include  "stdafx.h" 
#include<iostream> 
using namespace std; 
 
 
//操作系统  
class OS
{
public:
virtual void InstallOS_Imp() = 0;
};




class WindowOS : public OS
{
public:
void InstallOS_Imp() { cout << "安装Window操作系统" << endl; }
};
class LinuxOS : public OS
{
public:
void InstallOS_Imp() { cout << "安装Linux操作系统" << endl; }
};
class UnixOS : public OS
{
public:
void InstallOS_Imp() { cout << "安装Unix操作系统" << endl; }
};




//计算机  
class Computer

public:


OS *pOS;
virtual void InstallOS() = 0;
};




class DellComputer : public Computer
{
public:
void InstallOS( ) { 
cout << "Dell  Computer";
pOS->InstallOS_Imp();
}
};




class AppleComputer : public Computer
{
public:
void InstallOS() {
cout << "Apple  Computer";
pOS->InstallOS_Imp();
}
};




class HPComputer : public Computer
{
public:
void InstallOS() {
cout << "HP  Computer";
pOS->InstallOS_Imp();
}
};


 




int main()
{
 
OS *os1 = new WindowOS();
OS *os2 = new LinuxOS();


Computer *c1 = new AppleComputer( );
c1->pOS = os1;
c1->InstallOS(); 


c1->pOS = os2;
c1->InstallOS();




Computer *c2 = new HPComputer();
c2->pOS = os1;
c2->InstallOS();


c2->pOS = os2;
c2->InstallOS();
 
}

0 0