概述
- 属于“单一职责”模式(子类膨胀,需要划清职责)
- 属于结构型模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而在开发时分别使用
- 动机:某些类型固有的实现逻辑,使得它们有多个变化的维度
- 如何应对多维度变化,如何利用面向对象技术来使得类型可以轻松沿着多个方向变化,而不引入额外的复杂度?
- 将不同变化方向的函数(平台实现(Login / SendMessage)/业务抽象(PlaySound() / DrawShape()))放在两个类中
- 将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化
- 使用了对象间的组合关系解耦了抽象和现实间固有的绑定关系,使得抽象和实现可以沿着各自的维度变化
- Bridge类似于多继承,但多继承往往违背单一职责原则(一个类只有一个变化原因),复用性差
- 将实际程序分为抽象部分(用户界面[GUI])和实现部分(底层操作系统代码[API]),GUI调用API对用户的操作做出响应
- 可以在两个独立方向对应用进行扩展,如开发多个GUI(面向普通用户和管理员),支持多个不同的API(面向Windows,Linux,MacOS)
- 客户端代码将实现对象传递给抽象部分的构造函数,此后只需与抽象部分打交互,而无需操作实现对象
示例1
- bridge1.cpp:1+n+m*n
- bridge2.cpp:1+n+m
- imp->OperationImp(); 相当于 MessagerImp* messagerImp;
- Implementor 相当于 MessagerImp
- ConcreteImplementor A 相当于 PCMessagerImp
- RefinedAbstraction 相当于 MessagerLite, MessagerPerfect
bridge1.cpp
1 class Messager{ 2 public: 3 virtual void Login(string username, string password)=0; 4 virtual void SendMessage(string message)=0; 5 virtual void SendPicture(Image image)=0; 6 7 virtual void PlaySound()=0; 8 virtual void DrawShape()=0; 9 virtual void WriteText()=0; 10 virtual void Connect()=0; 11 12 virtual ~Messager(){} 13 }; 14 15 //平台实现 16 17 class PCMessagerBase : public Messager{ 18 public: 19 20 virtual void PlaySound(){ 21 //********** 22 } 23 virtual void DrawShape(){ 24 //********** 25 } 26 virtual void WriteText(){ 27 //********** 28 } 29 virtual void Connect(){ 30 //********** 31 } 32 }; 33 34 class MobileMessagerBase : public Messager{ 35 public: 36 37 virtual void PlaySound(){ 38 //========== 39 } 40 virtual void DrawShape(){ 41 //========== 42 } 43 virtual void WriteText(){ 44 //========== 45 } 46 virtual void Connect(){ 47 //========== 48 } 49 }; 50 51 //业务抽象 52 53 class PCMessagerLite : public PCMessagerBase { 54 public: 55 56 virtual void Login(string username, string password){ 57 58 PCMessagerBase::Connect(); 59 //........ 60 } 61 virtual void SendMessage(string message){ 62 63 PCMessagerBase::WriteText(); 64 //........ 65 } 66 virtual void SendPicture(Image image){ 67 68 PCMessagerBase::DrawShape(); 69 //........ 70 } 71 }; 72 73 class PCMessagerPerfect : public PCMessagerBase { 74 public: 75 76 virtual void Login(string username, string password){ 77 78 PCMessagerBase::PlaySound(); 79 //******** 80 PCMessagerBase::Connect(); 81 //........ 82 } 83 virtual void SendMessage(string message){ 84 85 PCMessagerBase::PlaySound(); 86 //******** 87 PCMessagerBase::WriteText(); 88 //........ 89 } 90 virtual void SendPicture(Image image){ 91 92 PCMessagerBase::PlaySound(); 93 //******** 94 PCMessagerBase::DrawShape(); 95 //........ 96 } 97 }; 98 99 class MobileMessagerLite : public MobileMessagerBase { 100 public: 101 102 virtual void Login(string username, string password){ 103 104 MobileMessagerBase::Connect(); 105 //........ 106 } 107 virtual void SendMessage(string message){ 108 109 MobileMessagerBase::WriteText(); 110 //........ 111 } 112 virtual void SendPicture(Image image){ 113 114 MobileMessagerBase::DrawShape(); 115 //........ 116 } 117 }; 118 119 class MobileMessagerPerfect : public MobileMessagerBase { 120 public: 121 122 virtual void Login(string username, string password){ 123 124 MobileMessagerBase::PlaySound(); 125 //******** 126 MobileMessagerBase::Connect(); 127 //........ 128 } 129 virtual void SendMessage(string message){ 130 131 MobileMessagerBase::PlaySound(); 132 //******** 133 MobileMessagerBase::WriteText(); 134 //........ 135 } 136 virtual void SendPicture(Image image){ 137 138 MobileMessagerBase::PlaySound(); 139 //******** 140 MobileMessagerBase::DrawShape(); 141 //........ 142 } 143 }; 144 145 void Process(){ 146 //编译时装配 147 Messager *m = 148 new MobileMessagerPerfect(); 149 }
bridge2.cpp
1 class Messager{ 2 protected: 3 MessagerImp* messagerImp;//... 4 public: 5 virtual void Login(string username, string password)=0; 6 virtual void SendMessage(string message)=0; 7 virtual void SendPicture(Image image)=0; 8 9 virtual ~Messager(){} 10 }; 11 12 class MessagerImp{ 13 public: 14 virtual void PlaySound()=0; 15 virtual void DrawShape()=0; 16 virtual void WriteText()=0; 17 virtual void Connect()=0; 18 19 virtual MessagerImp(){} 20 }; 21 22 //平台实现 n 23 class PCMessagerImp : public MessagerImp{ 24 public: 25 26 virtual void PlaySound(){ 27 //********** 28 } 29 virtual void DrawShape(){ 30 //********** 31 } 32 virtual void WriteText(){ 33 //********** 34 } 35 virtual void Connect(){ 36 //********** 37 } 38 }; 39 40 class MobileMessagerImp : public MessagerImp{ 41 public: 42 43 virtual void PlaySound(){ 44 //========== 45 } 46 virtual void DrawShape(){ 47 //========== 48 } 49 virtual void WriteText(){ 50 //========== 51 } 52 virtual void Connect(){ 53 //========== 54 } 55 }; 56 57 //业务抽象 m 58 59 //类的数目:1+n+m 60 61 class MessagerLite :public Messager { 62 63 64 public: 65 66 virtual void Login(string username, string password){ 67 68 messagerImp->Connect(); 69 //........ 70 } 71 virtual void SendMessage(string message){ 72 73 messagerImp->WriteText(); 74 //........ 75 } 76 virtual void SendPicture(Image image){ 77 78 messagerImp->DrawShape(); 79 //........ 80 } 81 }; 82 83 class MessagerPerfect :public Messager { 84 85 86 public: 87 88 virtual void Login(string username, string password){ 89 90 messagerImp->PlaySound(); 91 //******** 92 messagerImp->Connect(); 93 //........ 94 } 95 virtual void SendMessage(string message){ 96 97 messagerImp->PlaySound(); 98 //******** 99 messagerImp->WriteText(); 100 //........ 101 } 102 virtual void SendPicture(Image image){ 103 104 messagerImp->PlaySound(); 105 //******** 106 messagerImp->DrawShape(); 107 //........ 108 } 109 }; 110 111 void Process(){ 112 //运行时装配 113 MessagerImp* mImp=new PCMessagerImp(); 114 Messager *m =new Messager(mImp); 115 }
示例2
1 #include <string> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 6 /** 7 * The Implementation defines the interface for all implementation classes. It 8 * doesn't have to match the Abstraction's interface. In fact, the two 9 * interfaces can be entirely different. Typically the Implementation interface 10 * provides only primitive operations, while the Abstraction defines higher- 11 * level operations based on those primitives. 12 */ 13 14 class Implementation { 15 public: 16 virtual ~Implementation() {} 17 virtual std::string OperationImplementation() const = 0; 18 }; 19 20 /** 21 * Each Concrete Implementation corresponds to a specific platform and 22 * implements the Implementation interface using that platform's API. 23 */ 24 class ConcreteImplementationA : public Implementation { 25 public: 26 std::string OperationImplementation() const override { 27 return "ConcreteImplementationA: Here's the result on the platform A. "; 28 } 29 }; 30 class ConcreteImplementationB : public Implementation { 31 public: 32 std::string OperationImplementation() const override { 33 return "ConcreteImplementationB: Here's the result on the platform B. "; 34 } 35 }; 36 37 /** 38 * The Abstraction defines the interface for the "control" part of the two class 39 * hierarchies. It maintains a reference to an object of the Implementation 40 * hierarchy and delegates all of the real work to this object. 41 */ 42 43 class Abstraction { 44 /** 45 * @var Implementation 46 */ 47 protected: 48 Implementation* implementation_; 49 50 public: 51 Abstraction(Implementation* implementation) : implementation_(implementation) { 52 } 53 54 virtual ~Abstraction() { 55 } 56 57 virtual std::string Operation() const { 58 return "Abstraction: Base operation with: " + 59 this->implementation_->OperationImplementation(); 60 } 61 }; 62 /** 63 * You can extend the Abstraction without changing the Implementation classes. 64 */ 65 class ExtendedAbstraction : public Abstraction { 66 public: 67 ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) { 68 } 69 std::string Operation() const override { 70 return "ExtendedAbstraction: Extended operation with: " + 71 this->implementation_->OperationImplementation(); 72 } 73 }; 74 75 /** 76 * Except for the initialization phase, where an Abstraction object gets linked 77 * with a specific Implementation object, the client code should only depend on 78 * the Abstraction class. This way the client code can support any abstraction- 79 * implementation combination. 80 */ 81 void ClientCode(const Abstraction& abstraction) { 82 // ... 83 std::cout << abstraction.Operation(); 84 // ... 85 } 86 /** 87 * The client code should be able to work with any pre-configured abstraction- 88 * implementation combination. 89 */ 90 91 int main() { 92 Implementation* implementation = new ConcreteImplementationA; 93 Abstraction* abstraction = new Abstraction(implementation); 94 ClientCode(*abstraction); 95 std::cout << std::endl; 96 delete implementation; 97 delete abstraction; 98 99 implementation = new ConcreteImplementationB; 100 abstraction = new ExtendedAbstraction(implementation); 101 ClientCode(*abstraction); 102 103 delete implementation; 104 delete abstraction; 105 106 return 0; 107 }
与其他模式关系
- 桥接模式用于开发前期的设计,让程序的各个不同部分独立开发;适配器模式用于已有程序中,让不兼容的类实现合作
- 桥接、状态、策略模式都基于组合模式,即将工作委派给其他对象
- 可与抽象工厂搭配使用
- 可与生成器搭配使用
参考