C++设计模式编程中使用Bridge桥接模式的完全攻略


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

桥接模式典型的结构图为:

在桥接模式的结构图中可以看到,系统被分为两个相对独立的部分,左边是抽象部分,右边是实现部分,这两个部分可以互相独立地进行修改:例如上面问题中的客户需求变化,当用户需求需要从 Abstraction 派生一个具体子类时候,并不需要像上面通过继承方式实现时候需要添加子类 A1 和 A2 了。另外当上面问题中由于算法添加也只用改变右边实现(添加一个具体化子类),而右边不用在变化,也不用添加具体子类了。

一切都变得 elegant!

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

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

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

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

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

抽象基类及接口:

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

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

3、在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.将可以共享的变化部分,抽离出来,减少了代码的重复信息。

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

缺点
客户必须知道选择哪一种类型的实现。
设计中有超过一维的变化我们就可以用桥模式。如果只有一维在变化,那么我们用继承就可以圆满的解决问题。

代码示例:

Abstraction.h

#ifndef _ABSTRACTION_H_
#define _ABSTRACTION_H_

class AbstractionImplement;

class Abstraction
{
public:
  virtual void Operation()=0;//定义接口,表示该类所支持的操作
  virtual ~Abstraction();
protected:
  Abstraction();
};

class RefinedAbstractionA:public Abstraction
{
public:
  RefinedAbstractionA(AbstractionImplement* imp);//构造函数
  virtual void Operation();//实现接口
  virtual ~RefinedAbstractionA();//析构函数
private:
  AbstractionImplement* _imp;//私有成员
};

class RefinedAbstractionB:public Abstraction
{
public:
  RefinedAbstractionB(AbstractionImplement* imp);//构造函数
  virtual void Operation();//实现接口
  virtual ~RefinedAbstractionB();//析构函数
private:
  AbstractionImplement* _imp;//私有成员
};
#endif

Abstraction.cpp
#include "Abstraction.h"
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

Abstraction::Abstraction()
{}

Abstraction::~Abstraction()
{}

RefinedAbstractionA::RefinedAbstractionA(AbstractionImplement* imp)
{
  this->_imp = imp;
}

RefinedAbstractionA::~RefinedAbstractionA()
{
  delete this->_imp;
  this->_imp = NULL;
}

void RefinedAbstractionA::Operation()
{
  cout << "RefinedAbstractionA::Operation" << endl;
  this->_imp->Operation();
}

RefinedAbstractionB::RefinedAbstractionB(AbstractionImplement* imp)
{
  this->_imp = imp;
}

RefinedAbstractionB::~RefinedAbstractionB()
{
  delete this->_imp;
  this->_imp = NULL;
}

void RefinedAbstractionB::Operation()
{
  cout << "RefinedAbstractionB::Operation" << endl;
  this->_imp->Operation();
}

AbstractImplement.h
#ifndef _ABSTRACTIONIMPLEMENT_H_
#define _ABSTRACTIONIMPLEMENT_H_

//抽象基类,定义了实现的接口
class AbstractionImplement
{
public:
  virtual void Operation()=0;//定义操作接口
  virtual ~AbstractionImplement();
protected:
  AbstractionImplement();
};

// 继承自AbstractionImplement,是AbstractionImplement的不同实现之一
class ConcreteAbstractionImplementA:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementA();
  void Operation();//实现操作
  ~ConcreteAbstractionImplementA();
protected:
};

// 继承自AbstractionImplement,是AbstractionImplement的不同实现之一
class ConcreteAbstractionImplementB:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementB();
  void Operation();//实现操作
  ~ConcreteAbstractionImplementB();
protected:
};
#endif

AbstractImplement.cpp
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

AbstractionImplement::AbstractionImplement()
{}

AbstractionImplement::~AbstractionImplement()
{}

ConcreteAbstractionImplementA::ConcreteAbstractionImplementA()
{}

ConcreteAbstractionImplementA::~ConcreteAbstractionImplementA()
{}

void ConcreteAbstractionImplementA::Operation()
{
  cout << "ConcreteAbstractionImplementA Operation" << endl;
}

ConcreteAbstractionImplementB::ConcreteAbstractionImplementB()
{}

ConcreteAbstractionImplementB::~ConcreteAbstractionImplementB()
{}

void ConcreteAbstractionImplementB::Operation()
{
  cout << "ConcreteAbstractionImplementB Operation" << endl;
}

main.cpp

#include "Abstraction.h"
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

int main()
{
  /* 将抽象部分与它的实现部分分离,使得它们可以独立地变化

  1、抽象Abstraction与实现AbstractionImplement分离;

  2、抽象部分Abstraction可以变化,如new RefinedAbstractionA(imp)、new RefinedAbstractionB(imp2);

  3、实现部分AbstractionImplement也可以变化,如new ConcreteAbstractionImplementA()、new ConcreteAbstractionImplementB();

  */

  AbstractionImplement* imp = new ConcreteAbstractionImplementA();    //实现部分ConcreteAbstractionImplementA
  Abstraction* abs = new RefinedAbstractionA(imp);            //抽象部分RefinedAbstractionA
  abs->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp1 = new ConcreteAbstractionImplementB();    //实现部分ConcreteAbstractionImplementB
  Abstraction* abs1 = new RefinedAbstractionA(imp1);            //抽象部分RefinedAbstractionA
  abs1->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp2 = new ConcreteAbstractionImplementA();    //实现部分ConcreteAbstractionImplementA
  Abstraction* abs2 = new RefinedAbstractionB(imp2);            //抽象部分RefinedAbstractionB
  abs2->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp3 = new ConcreteAbstractionImplementB();    //实现部分ConcreteAbstractionImplementB
  Abstraction* abs3 = new RefinedAbstractionB(imp3);            //抽象部分RefinedAbstractionB
  abs3->Operation();

  cout << endl;
  return 0;
}

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

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

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

备注:

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

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

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

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

适用场景:

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时B r i d g e 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
  • (C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
  • 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。R u m b a u g h 称这种类层次结构为“嵌套的普化”(nested generalizations )。
  • 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是C o p l i e n 的S t r i n g 类[ C o p 9 2 ],在这个类中多个对象可以共享同一个字符串表示(S t r i n g R e p )。



相关阅读:
浅谈jQuery的offset()方法及示例分享
Asp.Mvc 2.0用户服务器验证实例讲解(4)
win7系统戴尔笔记本电脑突然关机的多种原因及解决方法
Win7系统弹出Adobe Flash Player已停止工作窗口的解决方法
ext前台接收action传过来的json数据示例
Win10 Build 10151手机版曝光 视频演示过渡动画
C#获得MAC地址(网卡序列号)的实现代码
C#实现洗牌算法
ASP.NET页面间数据传递的几种方法介绍
.NET 正则表达式使用高级技巧之替换类介绍
PHP面试题之文件目录操作
ASP.NET My97DatePicker日期控件实现OA日期记事功能
C#处理Paint事件的方法
PHP中static关键字以及与self关键字的区别
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 副市长在医院建院50周年庆典上的贺词 美丽的彩虹作文500字 德天瀑布300字 月亮在天空分发银币 《拇指姑娘》续写作文1000字 一千个男人追你,未必有一个男人爱你。 周一短信 先进性教育活动个人第三阶段整改方案 党性分析材料(万能版) 爱不是拥有 恭迎村神驾到!作文800字 小学生寒假社会实践心得体会 2013年教师工作总结 个人 听说幸福很简单,简单到时间一冲就冲淡 2015自传范文入党 医院制剂室扩建项目建议书 初中初一作文700字:人生的斯诺克 《封神演义》续写 2013年学院中秋晚会活动方案 观“普法宣传节目”有感650字 三岁开始 宝宝成了“好色之徒” 【精品】解方程教学反思 护士找工作成都 信任比什么都重要作文400字 我对感情生活的观点 党员志愿者活动方案 三篇 我的紫茉莉 美丽的宝安公园作文500字 在走丢了你名字的路上 住字的组词大全 我当小小保洁员 小学英语教育见习实践报告 2016—2017学年第一学期工作总结 青春励志:会赚钱是一种能力 关于爱国的散文 太阳岛游记 2016早教前台年终工作总结范文 游古寨作文550字 高中高三作文1500字:赞竹情节 分公司合作协议范本 除夕诗兴 马嵬驿·玉颜虽掩马 描写秋天树叶的段落 国家资助助我成长 医院发展我有责 《一位教师的微信》读后感 小学五年级作文750字:电脑足球比赛 妇女节礼物祝福语 忘不了学校的建筑作文450字 失恋后的说说心情:你什么都不知道,包括我喜欢你

Copyright © 2016 phpStudy |