C++设计模式-Bridge桥接模式

做用:将抽象部份与它的实现部份分离,使它们均可以独立地变化。ios

将抽象(Abstraction)与实现(Implementation)分离,使得两者能够独立地变化。编程

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

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

手机品牌和软件是两个概念,不一样的软件能够在不一样的手机上,不一样的手机能够有相同的软件,二者都具备很大的变更性。若是咱们单独以手机品牌或手机软件为基类来进行继承扩展的话,无疑会使类的数目剧增而且耦合性很高,(若是更改品牌或增长软件都会增长不少的变更)两种方式的结构以下:ui

 

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

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

 UML结构图以下:设计

抽象基类及接口:指针

一、Abstraction::Operation():定义要实现的操做接口code

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

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

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

Bridge的实现方式其实和Builde十分的相近,能够这么说:本质上是同样的,只是封装的东西不同罢了.二者的实现都有以下的共同点:

抽象出来一个基类,这个基类里面定义了共有的一些行为,造成接口函数(对接口编程而不是对实现编程),这个接口函数在Buildier中是BuildePart函数在Bridge中是Operation函数;

其次,聚合一个基类的指针,如Builder模式中Director类聚合了一个Builder基类的指针,而Brige模式中Abstraction类聚合了一个AbstractionImplement基类的指针(优先采用聚合而不是继承);

而在使用的时候,都把对这个类的使用封装在一个函数中,在Bridge中是封装在Director::Construct函数中,由于装配不一样部分的过程是一致的,而在Bridge模式中则是封装在Abstraction::Operation函数中,在这个函数中调用对应的AbstractionImplement::Operation函数.就两个模式而言,Builder封装了不一样的生成组成部分的方式,而Bridge封装了不一样的实现方式.

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

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

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

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

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

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

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

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

 

设计中有超过一维的变化咱们就能够用桥模式。若是只有一维在变化,那么咱们用继承就能够圆满的解决问题。

 代码以下:

Abstraction.h

 1 #ifndef _ABSTRACTION_H_
 2 #define _ABSTRACTION_H_
 3 
 4 class AbstractionImplement;
 5 
 6 class Abstraction
 7 {
 8 public:
 9     virtual void Operation()=0;//定义接口,表示该类所支持的操做
10     virtual ~Abstraction();
11 protected:
12     Abstraction();
13 };
14 
15 class RefinedAbstractionA:public Abstraction
16 {
17 public:
18     RefinedAbstractionA(AbstractionImplement* imp);//构造函数
19     virtual void Operation();//实现接口
20     virtual ~RefinedAbstractionA();//析构函数
21 private:
22     AbstractionImplement* _imp;//私有成员
23 };
24 
25 class RefinedAbstractionB:public Abstraction
26 {
27 public:
28     RefinedAbstractionB(AbstractionImplement* imp);//构造函数
29     virtual void Operation();//实现接口
30     virtual ~RefinedAbstractionB();//析构函数
31 private:
32     AbstractionImplement* _imp;//私有成员
33 };
34 #endif

Abstraction.cpp

 1 #include "Abstraction.h"
 2 #include "AbstractionImplement.h"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 Abstraction::Abstraction()
 8 {}
 9 
10 Abstraction::~Abstraction()
11 {}
12 
13 RefinedAbstractionA::RefinedAbstractionA(AbstractionImplement* imp)
14 {
15     this->_imp = imp;
16 }
17 
18 RefinedAbstractionA::~RefinedAbstractionA()
19 {
20     delete this->_imp;
21     this->_imp = NULL;
22 }
23 
24 void RefinedAbstractionA::Operation()
25 {
26     cout << "RefinedAbstractionA::Operation" << endl;
27     this->_imp->Operation();
28 }
29 
30 RefinedAbstractionB::RefinedAbstractionB(AbstractionImplement* imp)
31 {
32     this->_imp = imp;
33 }
34 
35 RefinedAbstractionB::~RefinedAbstractionB()
36 {
37     delete this->_imp;
38     this->_imp = NULL;
39 }
40 
41 void RefinedAbstractionB::Operation()
42 {
43     cout << "RefinedAbstractionB::Operation" << endl;
44     this->_imp->Operation();
45 }

AbstractImplement.h

 1 #ifndef _ABSTRACTIONIMPLEMENT_H_
 2 #define _ABSTRACTIONIMPLEMENT_H_
 3 
 4 //抽象基类,定义了实现的接口
 5 class AbstractionImplement
 6 {
 7 public:
 8     virtual void Operation()=0;//定义操做接口
 9     virtual ~AbstractionImplement();
10 protected:
11     AbstractionImplement();
12 };
13 
14 // 继承自AbstractionImplement,是AbstractionImplement的不一样实现之一
15 class ConcreteAbstractionImplementA:public AbstractionImplement
16 {
17 public:
18     ConcreteAbstractionImplementA();
19     void Operation();//实现操做
20     ~ConcreteAbstractionImplementA();
21 protected:
22 };
23 
24 // 继承自AbstractionImplement,是AbstractionImplement的不一样实现之一
25 class ConcreteAbstractionImplementB:public AbstractionImplement
26 {
27 public:
28     ConcreteAbstractionImplementB();
29     void Operation();//实现操做
30     ~ConcreteAbstractionImplementB();
31 protected:
32 };
33 #endif

AbstractImplement.cpp

 1 #include "AbstractionImplement.h"
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 AbstractionImplement::AbstractionImplement()
 7 {}
 8 
 9 AbstractionImplement::~AbstractionImplement()
10 {}
11 
12 ConcreteAbstractionImplementA::ConcreteAbstractionImplementA()
13 {}
14 
15 ConcreteAbstractionImplementA::~ConcreteAbstractionImplementA()
16 {}
17 
18 void ConcreteAbstractionImplementA::Operation()
19 {
20     cout << "ConcreteAbstractionImplementA Operation" << endl;
21 }
22 
23 ConcreteAbstractionImplementB::ConcreteAbstractionImplementB()
24 {}
25 
26 ConcreteAbstractionImplementB::~ConcreteAbstractionImplementB()
27 {}
28 
29 void ConcreteAbstractionImplementB::Operation()
30 {
31     cout << "ConcreteAbstractionImplementB Operation" << endl;
32 }

main.cpp

 1 #include "Abstraction.h"
 2 #include "AbstractionImplement.h"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     /* 将抽象部分与它的实现部分分离,使得它们能够独立地变化
10 
11     一、抽象Abstraction与实现AbstractionImplement分离;
12 
13     二、抽象部分Abstraction能够变化,如new RefinedAbstractionA(imp)、new RefinedAbstractionB(imp2);
14 
15     三、实现部分AbstractionImplement也能够变化,如new ConcreteAbstractionImplementA()、new ConcreteAbstractionImplementB();
16 
17     */
18 
19     AbstractionImplement* imp = new ConcreteAbstractionImplementA();        //实现部分ConcreteAbstractionImplementA
20     Abstraction* abs = new RefinedAbstractionA(imp);                        //抽象部分RefinedAbstractionA
21     abs->Operation();
22 
23     cout << "-----------------------------------------" << endl;
24 
25     AbstractionImplement* imp1 = new ConcreteAbstractionImplementB();        //实现部分ConcreteAbstractionImplementB
26     Abstraction* abs1 = new RefinedAbstractionA(imp1);                        //抽象部分RefinedAbstractionA
27     abs1->Operation();
28 
29     cout << "-----------------------------------------" << endl;
30 
31     AbstractionImplement* imp2 = new ConcreteAbstractionImplementA();        //实现部分ConcreteAbstractionImplementA
32     Abstraction* abs2 = new RefinedAbstractionB(imp2);                        //抽象部分RefinedAbstractionB
33     abs2->Operation();
34 
35     cout << "-----------------------------------------" << endl;
36 
37     AbstractionImplement* imp3 = new ConcreteAbstractionImplementB();        //实现部分ConcreteAbstractionImplementB
38     Abstraction* abs3 = new RefinedAbstractionB(imp3);                        //抽象部分RefinedAbstractionB
39     abs3->Operation();
40 
41     cout << endl;
42     return 0;
43 }

代码说明:
Bridge模式将抽象和实现分别独立实现,在代码中就是Abstraction类和AbstractionImplement类。

使用组合(委托)的方式将抽象和实现完全地解耦,这样的好处是抽象和实现能够分别独立地变化,系统的耦合性也获得了很好的下降。
GoF的那句话中的“实现”该怎么去理解:“实现”特别是和“抽象”放在一块儿的时候咱们“默认”的理解是“实现”就是“抽象”的具体子类的实现,可是这里GoF所谓的“实现”的含义不是指抽象基类的具体子类对抽象基类中虚函数(接口)的实现,是和继承结合在一块儿的。而这里的“实现”的含义指的是怎么去实现用户的需求,而且指的是经过组合(委托)的方式实现的,所以这里的实现不是指的继承基类、实现基类接口,而是指的是经过对象组合实现用户的需求。

实际上上面使用Bridge模式和使用带来问题方式的解决方案的根本区别在因而经过继承仍是经过组合的方式去实现一个功能需求。

备注:

因为实现的方式有多种,桥接模式的核心就是把这些实现独立出来,让他们各自变化。

将抽象部分与它的实现部分分离:实现系统可能有多角度(维度)分类,每一种分类均可能变化,那么就把这种多角度分离出来让它们独立变化,减小它们之间的耦合。

在发现须要多角度去分类实现对象,而只用继承会形成大量的类增长,不能知足开放-封闭原则时,就要考虑用Bridge桥接模式了。

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