c++ 设计模式7 (Bridge 桥模式)
4.2 Bridge 桥模式
动机:
由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度。
代码示例:
实现一个Messager,含有基本功能PlaySound,Connect等,并有PC、Mobile不同的平台实现 和 精简、完美等不同业务功能的版本
实现方法1:
Bridge1.cpp
类的个数:1 + n + m*n,数量巨大且不同类之中有大量重复
重构见方法2
class Messager{
public:
virtual void Login(string username, string password)=;
virtual void SendMessage(string message)=;
virtual void SendPicture(Image image)=; virtual void PlaySound()=;
virtual void DrawShape()=;
virtual void WriteText()=;
virtual void Connect()=; virtual ~Messager(){}
}; //平台实现 class PCMessagerBase : public Messager{
public: virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
}; class MobileMessagerBase : public Messager{
public: virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
}; //业务抽象 class PCMessagerLite : public PCMessagerBase {
public: virtual void Login(string username, string password){ PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ PCMessagerBase::DrawShape();
//........
}
}; class PCMessagerPerfect : public PCMessagerBase {
public: virtual void Login(string username, string password){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::DrawShape();
//........
}
}; class MobileMessagerLite : public MobileMessagerBase {
public: virtual void Login(string username, string password){ MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ MobileMessagerBase::DrawShape();
//........
}
}; class MobileMessagerPerfect : public MobileMessagerBase {
public: virtual void Login(string username, string password){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::DrawShape();
//........
}
}; void Process(){
//编译时装配
Messager *m =
new MobileMessagerPerfect();
}
重构步骤:
1.继承转组合,将PCMessagerBase,Mobilemessager声明为字段;
class PCMessagerLite {
PCMessagerBase *messager;
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
}; class PCMessagerLite {
MobileMessagerBase *messager;
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
};
2.观察上述两个类,发现只有 *messager 声明不同,故采用基类声明,运行时多态调用方式,创建不同的 PCMessagerBase,Mobilemessager;
class PCMessagerLite {
Messager *messager; // = new PCMessagerBase()或 MobileMessagerBase()
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
};
3.考虑步骤2的代码,Messager类是纯虚基类(抽象类),不能实例化,故= new ...不成立。
分析产生这种状况的原因,是Login,SendPicture等与平台实现相关的方法,和PlaySound,DrawShape等与业务功能相关的方法不应该在一个类里。
将其拆分,得到MessagerImp类。
同时将MessagerLite,MessagerPerfect类中相同的MesseagerImp字段提到父类Messager,得到重构后的代码
注意运行时装配
class Messager{
protected:
MessagerImp* messagerImp;//...
public:
virtual void Login(string username, string password)=;
virtual void SendMessage(string message)=;
virtual void SendPicture(Image image)=; virtual ~Messager(){}
}; class MessagerImp{
public:
virtual void PlaySound()=;
virtual void DrawShape()=;
virtual void WriteText()=;
virtual void Connect()=; virtual MessagerImp(){}
}; //平台实现 n
class PCMessagerImp : public MessagerImp{
public: virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
}; class MobileMessagerImp : public MessagerImp{
public: virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
}; //业务抽象 m //类的数目:1+n+m class MessagerLite :public Messager { public: virtual void Login(string username, string password){ messagerImp->Connect();
//........
}
virtual void SendMessage(string message){ messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){ messagerImp->DrawShape();
//........
}
}; class MessagerPerfect :public Messager { public: virtual void Login(string username, string password){ messagerImp->PlaySound();
//********
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){ messagerImp->PlaySound();
//********
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){ messagerImp->PlaySound();
//********
messagerImp->DrawShape();
//........
}
}; void Process(){
//运行时装配
MessagerImp* mImp=new PCMessagerImp();
Messager *m =new Messager(mImp);
}
模式定义:
将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化。
类图:
要点总结:
Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象的实现可以沿着各自的维度来变化。所谓抽象和实现研制各自维度的变化,即“子类化”他们。
Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个雷只有一个变化的原因),复用性较差。Bridge模式是比多继承更好的解决方案。
Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也有多余两个的变化维度,这是可以使用Bridge的扩展模式。
c++ 设计模式7 (Bridge 桥模式)的更多相关文章
- 设计模式 - Bridge 桥模式
Bridge桥模式也属于"的单一职责"模式中的典型模式.问题描述:我们绘制图形时,图形可以有不同形状以及不同颜色,比如圆形可以是红的,绿的,方形可以是红的绿的,如果用代码来描绘这些 ...
- Bridge 桥模式
之前一直以为桥是简单地沟通几个不同接口,使之能够按照一定流程工作.但重新查了一下解释,才有新解. 对于同一个产品的不同影响因子,如果使用继承的话,则这些影响因子则会按照M1*M2* ... Mn的数量 ...
- 设计模式(7)--Bridge(桥接模式)--结构型
1.模式定义: 桥接模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式.桥接模式的用意是“将抽象化(Abstraction)与实现化(Impleme ...
- C++设计模式 之 “单一职责”模式:Decorator、Bridge
part 1 “单一职责”模式 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任. 典型模式 Decorato ...
- 面向对象设计模式纵横谈:Bridge 桥接模式(笔记记录)
桥接模式是一个比较难理解的设计模式,设计和分析的时候也不容易把握,咱们听听“李建忠”老师是怎么来讲的.我们还是从演变的角度来说问题,一步一步的来把问题说清楚.先谈谈“抽象”和“实现”的关系. 抽象与实 ...
- Java设计模式(6)桥模式(Bridge模式)
Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合. 为什么使用桥模式 通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以 ...
- 设计模式---单一职责模式之桥模式(Bridge)
一:概念 Bridge模式又叫做桥接模式,其实基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任他的主要特点是吧抽象与行为实现分离开来,从而可以保持各部分的独立性以及一对 ...
- C++设计模式-Bridge桥接模式
作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化. 将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式 ...
- 设计模式的征途—8.桥接(Bridge)模式
在现实生活中,我们常常会用到两种或多种类型的笔,比如毛笔和蜡笔.假设我们需要大.中.小三种类型的画笔来绘制12中不同的颜色,如果我们使用蜡笔,需要准备3*12=36支.但如果使用毛笔的话,只需要提供3 ...
随机推荐
- Android签名用keytool和jarsigner制作apk文件
生成证书 keytool -genkey -alias aeo_android.keystore -keyalg RSA -validity -keystore aeo_android.keystor ...
- 【转】17种常用的JS正则表达式 非负浮点数 非负正数.
<input type='text' id='SYS_PAGE_JumpPage' name='SYS_PAGE_JumpPage' size='3' maxlength='5' onkeyup ...
- spring的annotation-driven配置事务管理器详解
http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html ——————————————————————————————————————————————— ...
- spring 的properties解析
一般使用PropertyPlaceholderConfigurer来替换占位符,例如: <bean class="org.springframework.beans.factory.c ...
- class int
class int(object): """ int(x=0) -> integer int(x, base=10) -> integer Convert a ...
- 安装Sass
最近要开始用 Sass 做一些东西.先来记录一下安装过程. 1.确认本机的 Ruby 版本 2.访问网址下载 Sass 最新版本 https://rubygems.org/gems/sass 3.下载 ...
- Codeforces 100548F - Color (组合数+容斥)
题目链接:http://codeforces.com/gym/100548/attachments 有n个物品 m种颜色,要求你只用k种颜色,且相邻物品的颜色不能相同,问你有多少种方案. 从m种颜色选 ...
- HDU 3920Clear All of Them I(状压DP)
HDU 3920 Clear All of Them I 题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人 ...
- lib和dll的例子
.dll和.lib的区别 lib是静态库,dll一般是动态链接库(也有可能是别的)比如要编译个exe,lib在编译的时候就会被编译到exe里,作为程序的一部分而dll是不被编译进去,是运行的时候才调入 ...
- (图解版)SQL Server数据库备份与还原
本文介绍了SQL Server数据库备份的两种方式.一种是直接拷贝数据库中的文件mdf 和日志文件ldf,另一种是生成脚本语言. 第一种方式: 选中需要备份的数据库,将数据库从运行的数 ...