建站系统cms是什么,asp网站图片,中国进出口企业名录,站长网网站模板下载文章目录 1. 动机#xff08;Motivation#xff09;2. 代码演示Bridge 桥模式2.1 基于继承的常规思维处理2.2 基于组合关系的重构优化2.3 采用Bridge 桥模式的实现 3. 模式定义4. 结构#xff08;Structure#xff09;5. 要点总结 与上篇介绍的Decorator 装饰模式一样… 文章目录 1. 动机Motivation2. 代码演示Bridge 桥模式2.1 基于继承的常规思维处理2.2 基于组合关系的重构优化2.3 采用Bridge 桥模式的实现 3. 模式定义4. 结构Structure5. 要点总结 与上篇介绍的Decorator 装饰模式一样Bridge 桥模式也属于典型的“单一职责”模式在特性上也与Decorator 装饰模式存在很多类似但也存在不同得到地方。
“单一职责”模式的主要特征为“在软件组件的设计中如果责任划分的不清晰使用继承得到的结果往往是随着需求的变化子类急剧膨胀同时充斥着重复代码这时候的关键是划清责任。”
1. 动机Motivation 由于某些类型的固有的实现逻辑使得它们具有两个变化的维度乃至多个纬度的变化。 如何应对这种“多维度的变化”如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化而不引入额外的复杂度
2. 代码演示Bridge 桥模式
针对上面的理解还是需要回到代码进行理解。
2.1 基于继承的常规思维处理
下面的代码是一个简单的通信模块实现的功能包括Login()、SendMessage()…等。
class Messager{
public:virtual void Login(string username, string password)0;virtual void SendMessage(string message)0;virtual void SendPicture(Image image)0;virtual void PlaySound()0;virtual void DrawShape()0;virtual void WriteText()0;virtual void Connect()0;virtual ~Messager(){}
};然后需要进行PC平台的设计但是由于平台的不同需要override PlaySound()、DrawShape()、WriteText()、Connect()
class PCMessagerBase : public Messager{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};类似PC平台的设计Mobile上的设计也需要对相应的功能override
class MobileMessagerBase : public Messager{
public:virtual void PlaySound(){//}virtual void DrawShape(){//}virtual void WriteText(){//}virtual void Connect(){//}
};另外我们可能会有在不同平台出“精简版”、“完美版”的需求例如在PC平台中class PCMessagerLite : public PCMessagerBase其中实现了某些功能而在class PCMessagerPerfect : public PCMessagerBase这个时候“完美版”在实现功能时会有更多的功能内容但是最基本的是一样都是调用PCMessagerBase的方法。同样在Mobile平台也是有“精简版”、“完美版”的需求虽然平台不同但是业务功能需求也是一样的。
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();//........}
};整体代码如下
class Messager{
public:virtual void Login(string username, string password)0;virtual void SendMessage(string message)0;virtual void SendPicture(Image image)0;virtual void PlaySound()0;virtual void DrawShape()0;virtual void WriteText()0;virtual void Connect()0;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();
}以上是一种编译式装配的方式上面代码的框架不难画出得到如下图 2.2 基于组合关系的重构优化
如果将平台实现列为n的话将业务抽象列为m的话整体类的数目就是1nm*n此处不像Decorator 装饰模式中Lite和Perfect会有组合的情况这样就造成大量的类并且在类中的方法也是存在重复的例如
PCMessagerPerfect中的 virtual void Login(string username, string password){PCMessagerBase::PlaySound();//********PCMessagerBase::Connect();//........}MobileMessagerPerfect中的 virtual void Login(string username, string password){MobileMessagerBase::PlaySound();//********MobileMessagerBase::Connect();//........}上面的内容都是似曾相识的重复这种重复也是结构性的重复
以下内容都是相同的
//********
//........不同的就是PCMessagerBase::PlaySound();和MobileMessagerBase::PlaySound();PCMessagerBase::Connect();和MobileMessagerBase::Connect();
如果有Decorator 装饰模式基础的话可以发现可以使用继承转组合进行重构例如将class PCMessagerPerfect : public PCMessagerBase { }中的父类变为数据成员class PCMessagerPerfect { PCMessagerBase* messager }声明为指针是因为指针具有多态性相应的Mobile平台的也进行修改。
class PCMessagerPerfect {PCMessagerBase* messager;public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};class MobileMessagerPerfect {MobileMessagerBase* messager;
public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};从上面的代码可以看到两个类不同的地方就是PCMessagerBase* messager;和MobileMessagerBase* messager;他们两个来自于一个基类因此可以改写为以下形式
class PCMessagerPerfect {Messager* messager; //未来运行时可以new PCMessagerPerfect();public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};class MobileMessagerPerfect {Messager* messager; //未来运行时可以new MobileMessagerPerfect();
public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};此时class PCMessagerPerfect和class PCMessagerPerfect已经没有什么区别了他们的区别就是在未来运行时编译时的代码就可以变为
class MessagerPerfect{Messager* messager; //未来运行时可以new PCMessagerPerfect()等;public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};class MessagerPerfect{Messager* messager; //未来运行时可以new MobileMessagerPerfect();
public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};这个时候发现两个类一模一样这个时候只需要保留一个即可同样的MessagerLite也是如法炮制变为如下形式
class MessagerLite{Messager* messager; //未来运行时可以new PCMessagerLite()等;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 Messager{
public:virtual void Login(string username, string password)0;virtual void SendMessage(string message)0;virtual void SendPicture(Image image)0;virtual void PlaySound()0;virtual void DrawShape()0;virtual void WriteText()0;virtual void Connect()0;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 MessagerLite{Messager* 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 MessagerPerfect{Messager* messager; //未来运行时可以new PCMessagerPerfect()等;public:virtual void Login(string username, string password){messager-PlaySound();//********messager-Connect();//........}virtual void SendMessage(string message){messager-PlaySound();//********messager-WriteText();//........}virtual void SendPicture(Image image){messager-PlaySound();//********messager-DrawShape();//........}
};void Process(){//编译时装配Messager *m new MobileMessagerPerfect();
}
此时可以发现 Messager* messager; //未来运行时可以new PCMessagerPerfect()等;是不成立的这是因为class PCMessagerBase是一个抽象类。 为什么说其是抽象类呢? 因为其只override了class Messager中的部分虚函数另外一些没有override。这个问题如何解决呢在子类中只使用到了基类class Messager的一部分函数里面的两个部分的函数塞在一起是不合适的应该将其拆分开。
class Messager{
public:virtual void Login(string username, string password)0;virtual void SendMessage(string message)0;virtual void SendPicture(Image image)0;virtual ~Messager(){}
};//平台实现
class MessagerImp{
public:virtual void PlaySound()0;virtual void DrawShape()0;virtual void WriteText()0;virtual void Connect()0;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//类的数目1nmclass MessagerLite :public Messager {Messager* messager; //未来运行时可以new PCMessagerLite()等;
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 {Messager* messager; //未来运行时可以new PCMessagerPerfect()等; 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();//........}
};
2.3 采用Bridge 桥模式的实现
上面也是继承转组合当做到这里已经接近完美同样的马丁福乐重构中讲到如果同样的子类中有通用的字段此处即为class MessagerLite :public Messager和class MessagerPerfect :public Messager中的Messager* messager;那么往上提到父类Messager中变为以下形式
class Messager{
protected:MessagerImp* messagerImp;//...
public:virtual void Login(string username, string password)0;virtual void SendMessage(string message)0;virtual void SendPicture(Image image)0;virtual ~Messager(){}
};class MessagerImp{
public:virtual void PlaySound()0;virtual void DrawShape()0;virtual void WriteText()0;virtual void Connect()0;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//类的数目1nmclass 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* mImpnew PCMessagerImp();Messager *m new Messager(mImp);
}当然需要父类提供构造函数去初始化MessagerImp* messagerImp;字段子类放一个构造函数去调用父类的构造函数即可此处未写。
此时就比较完美类的个数就变为1nm但是运行时还会有n*m的功能这里就是桥模式。
回过头来看在第一个版本中放了不同的函数有不同的变化方向一个变化方向是平台实现PC、Mobile一个变化方向是业务抽象Lite、Perfect这两个不同的变化方向带动的行为的多态的实现也应该是往不同的方向走也就不应该放在一个类中。
这也就体现了动机Motivation 中提到的多维度的变化 。
3. 模式定义
将抽象部分(业务功能)与实现部分(平台实现)分离使它们都可以独立地变化。
——《设计模式》GoF
4. 结构Structure 上图是《设计模式》GoF中定义的Bridge 桥模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分也就是下图中红框和蓝框框选的部分。
两个变化方向独立变化而不是搅在一起变化。
5. 要点总结 Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化即“子类化”它们。 Bridge模式有时候类似于多继承方案但是多继承方案往往违背单一职责原则即一个类只有一个变化的原因复用性比较差。Bridge模式是比多继承方案更好的解决方法。推荐一个单继承配合组合的模式 Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也有多于两个的变化维度这时可以使用Bridge的扩展模式。