桥接模式

意图:将抽象部分与它的实现部分分离,使他们都可以独立的变化。

抽象与实现分离:不是说,让抽象类与其派生类分离,实现指的是抽象类和它的派生类用来实现自己的对象。

如果系统可能有多个角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合,而且一般一个类层次的实现是借助另一个类层次实现的。

适用情况:

不希望在抽象与它的实现部分之间有一个固定的绑定关系。(例如在程序运行是苦实现部分可以被选择或者切换)

类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充,这时bridge模式可以使不同的抽象接口与实现部分进行组合,并分别扩充

对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译

(c++)向队客户完全隐藏抽象的实现部分,


      对象的继承关系是在编译时刻就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与父类的实现有非常紧密的依赖关系,以至于实现中的任何变化都必然会导致子类发生变化,当要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换,这种依赖关系限制了灵活性并最终限制了复用性。

合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承。

聚合表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;

合成是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的声明周期一样。

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

如下是两者关系:


翅膀属于大雁的一部分,而大雁只属于一个雁群,而一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。

对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

桥接模式结构图:


Abstraction:定义抽象类的接口,维护一个指向Implementor类型对象的指针。

RefinedAbstraction:扩充由Abstraction定义的接口

Implementor: 定义实现类的接口,该接口可以与Abstraction的接口不一样。一般来说:Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。

ConcreteImplementor:实现Implementor接口并定义它的具体实现。

协作:Abstraction将client的请求转发给它的Implementor对象。

Bridge优点:

1 分离接口与其实现部分:一个实现不用不变的绑定在一个接口上,抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。

2 提高可扩充性:可以独立的对abstraction与implementor层次进行扩充

3 实现细节对客户透明:对客户隐藏实现细节

实现:

1 仅有一个implementor:退化的情况,在abstraction与implementor之间只有一种一对一的关系。

2 创建正确的implementor对象:存在多个implementor对象,何时何处创建哪一个implementor类。一般有3种方法

(1)Abstraction知道所有的ConcreteImplementor类,可以在构造函数传递一个参数中对其中一个类进行实例化,

(2)首先选择一个缺省的实现,然后根据需要改变这个实现

(3)可以代理给另一个对象,由它决定,即可以引入一个factory对象,该对象的职责就是封装实现的细节,这个对象知道合适选择哪一个实现类,abstraction仅需要向它请求,就可以返回正确的实现对象。优点是任何一个abstraction对象与implementor对象不直接耦合

3 共享一个implementor对象

4 采用多重继承:在C++中可以用多重继承将抽象接口与实现部分结合起来,一个类可以用public方法继承abstraction而已private方式继承concreteimplementor.但这种方法是静态继承。即实现部分与接口固定不变的绑定在一起,即不可以用多重继承实现bridge模式。c++不行

相关模式:

Abstrat Factory可以用来搭建和配置一个特定的Bridge模式

Adapter模式用来帮助无关的类协同工作,通常在系统设计完成后才会被使用,

而Bridge模式则是在系统开始时就被使用,它是的抽象接口和实现部分可以独立进行改变。

以下为大话设计模式22章例子:

模式图:


代码如下:

//手机软件类
#ifndef TELSOFT_H
#define TELSOFT_H

#include <iostream>
using namespace std;

class HandsetSoft
{
public:
    virtual void Run() = 0;
};

//手机游戏
class HandsetGame : public HandsetSoft
{
public:
	void Run()
	{
		cout << "运行手机游戏" << endl;
	}
};

//手机通讯录
class HandSetAddressList : public HandsetSoft
{
public:
   void Run()
   {
	   cout << "运行手机通讯录" << endl;
   }
};
#endif

//手机品牌类
#ifndef TELBAND_H
#define TELBAND_H

#include "telsoft.h"

class HandsetBrand
{
public:
	virtual void Run() = 0;

	void SetHandsetSoft(HandsetSoft* soft)
	{
		_soft = soft;
	}
protected:
	HandsetSoft *_soft;
};

class HandsetBrandN : public HandsetBrand
{
public:
    void Run()
	{
        _soft->Run();
	}
};

class HandsetBrandM : public HandsetBrand
{
public:
	void Run()
	{
		_soft->Run();
	}
};
#endif


//Bridge客户端
#include "telband.h"

int main()
{
	HandsetBrand *ab;
	
	ab = new HandsetBrandN;
	ab->SetHandsetSoft(new HandsetGame);
	ab->Run();
	ab->SetHandsetSoft(new HandSetAddressList);
	ab->Run();

	ab = new HandsetBrandM;
	ab->SetHandsetSoft(new HandsetGame);
	ab->Run();
	ab->SetHandsetSoft(new HandSetAddressList);
	ab->Run();

	system("pause");
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值