桥接模式:

  桥接是用于把抽象化与实现化解耦,使得两者可以独立变化。

桥接模式的角色:

  1. 抽象化角色(Abstraction):它是用于定义抽象接口,通常是抽象类而不是接口,其中定义了一个Implementor(实现接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系。
  2. 改善后的抽象化角色(RefinedAbstraction):通常是具体类,实现了Abstraction中的抽象方法,在RefinedAbstraction中可以调用Implementor中定义的方法。
  3. 实现者角色(Implementor):通常情况下提供一些基本操作的声明,将具体实现交给其子类。
  4. 具体的实现者角色(ConcreteImplementorA、ConcreteImplementorB):实现了Implementor种定义的方法,运行时根据里氏替换原则,ConcreteImplementor对象将替换其父类对象,提供给抽象对象类具体的业务操作方法。

为什么使用桥接模式?

  我们都知道遥控器的通用功能是开机、关机,早先我们的做法应该是这样的:创建一个抽象遥控器类,里面定义开机、关机的一组方法,然后创建具体的遥控器类去继承或实现这个接口,这样就可以满足每个电视机的需求。但突然有一天,客户觉得这个遥控器的功能太少了,需要增加一个返回按钮,这个时候你傻眼了,你给抽象类添加了一个新方法,突然发现程序大面积报错,原因是子类未实现父类方法,于是霹雳巴拉一通改。好不容易改好了,客户又说了:想要一个菜单功能,于是….

  从上面的例子看出,这种设计违背了OCP原则,原因是类与类之间的耦合性过高,那怎样降低耦合呢?桥接模式是用于把抽象化和实现化解耦,使得两者可以独立变化。

优点:

抽象接口与其实现解耦,其中的抽象和实现可以独立的进行扩展,不会影响对方。

缺点:

增加了系统的复杂度。

使用场景:

  1. 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系;
  2. 设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的;
  3. 需要跨越多个平台的图形和窗口系统上;
  4. 一个类存在两个独立变化的维度,且两个维度都需要进行扩展。

区别:

桥接模式和适配器模式、代理模式的区别:

  1. 桥接模式提出是为了使用变化的,即需求发生多维度变化怎么办?而适配器模式的提出是为了解决兼容性问题,即由不兼容到兼容;代理模式提出主要是为了接口隔离。

eg:

class COS
{
public:
    virtual void Run(){}
};

class CLinuxOS : public COS
{
public:
    void Run(){cout << "LinuxOS run()" << endl;}
};

class CUnixOS : public COS
{
public:
    void Run(){cout << "CUnixOS run()" << endl;}
};
//------------------------------------
class CComputer
{
public:
    virtual void InstallOS(COS *os){}
};

class CIBMComputer : public CComputer
{
public:
    void InstallOS(COS *os){ os->Run();}
};

class CHPComputer : public CComputer
{
public:
    void InstallOS(COS *os){ os->Run();}
};
//------------------------------------
//use 
    COS *os = new CLinuxOS();
    CComputer *cmptr = new CIBMComputer();
    cmptr->InstallOS(os);