1, 功能:
将抽象部分与它的实现部分分离,使它们都可以独立的变化。换言之,就是实现共同点与变化点的分离(主要是外部的变化),将变化点封装成类进行处理。
2, 基本思想:
将时间的抽象与行为分开,使对象的属性与方法之间耦合度降低。只需要分别继承抽象的属性接口和方法接口就可以任意的“变化”具体对象的属性和方法。
3, 适用情况
不希望在抽象和它的实现部分之间有一个固定的绑定关系。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。Bridge模式可以对不同的抽象接口和实现部分进行组合,并分别对他们进行扩充。
对一个抽象的实现部分的修改对客户不产生影响,客户代码不必重新编译。
在C++中,类的表示在类接口中是可见的,Bridge方式对客户完全隐藏抽象的实现部分。
希望在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这点。
4, 结构

说明:
(1) Abstraction定义了抽象类的接口,它维护一个指向Implementor类型对象的指针;
(2) RefinedAbstraction实现Abstraction接口的方法;RefinedAbstraction类的对象才是真正要“Implemented”的对象;
(3) Implementor是实现类的接口,它不一定要求与Abstraction接口一致。一般来讲,Implementor接口仅提供基本操作,Abstraction定义的操作的具体实现通过Implementor接口的方法来实现。
(4) ConcreteImpementor接口实现了Implementor接口。
5, 举例
现在要设计一个绘图程序,可以画圆形和矩形。同时我们有两个不同版本的函数库,提供两套画图的实现(ShapeOne和ShapeTwo中分别调用两个库中的方法)。通常的实现方法,类的结构如下所示:

#include <iostream>
using namespace std;
// Draw with library 1
class CDrawLibOne
{
public:
void DrawCircle(){cout << "Draw circle with lib one" << endl;}
void DrawRectangle() {cout << "Draw rectangle with lib one" << endl;}
};
// Draw with library 2
class CDrawLibTwo
{
public:
void DrawCircle(){cout << "Draw circle with lib two" << endl;}
void DrawRectangle() {cout << "Draw rectangle with lib two" << endl;}
};
// CShapeOne class use library 1 to draw shapes
class CShapeOne
{
public:
virtual void Draw() = 0;
protected:
CDrawLibOne m_lib;
};
// CCircleOne and CRectangleOne class are derived from CShape class.
// They use CDrawLibOne to draw.
class CCircleOne : public CShapeOne
{
void Draw() {m_lib.DrawCircle();}
};
class CRectangleOne : public CShapeOne
{
void Draw() {m_lib.DrawRectangle();}
};
// CShapeTwo class use library 2 to draw shapes
class CShapeTwo
{
public:
virtual void Draw() = 0;
protected:
CDrawLibTwo m_lib;
};
// CCircleOne and CRectangleOne class are derived from CShape class.
// They use CDrawLibOne to draw.
class CCircleTwo : public CShapeTwo
{
void Draw() {m_lib.DrawCircle();}
};
class CRectangleTwo : public CShapeTwo
{
void Draw() {m_lib.DrawRectangle();}
};
// Define two global functions to draw with CShapeOne and CShapeTwo
void DrawOne(CShapeOne &s)
{
s.Draw();
}
void DrawTwo(CShapeTwo &s)
{
s.Draw();
}
// The client use above classes to draw
int main()
{
CCircleOne c1;
CCircleTwo c2;
CRectangleOne r1;
CRectangleTwo r2;
DrawOne(c1);
DrawOne(r1);
DrawTwo(c2);
DrawTwo(r2);
return 1;
}
using namespace std;
// Draw with library 1
class CDrawLibOne
{
public:
void DrawCircle(){cout << "Draw circle with lib one" << endl;}
void DrawRectangle() {cout << "Draw rectangle with lib one" << endl;}
};
// Draw with library 2
class CDrawLibTwo
{
public:
void DrawCircle(){cout << "Draw circle with lib two" << endl;}
void DrawRectangle() {cout << "Draw rectangle with lib two" << endl;}
};
// CShapeOne class use library 1 to draw shapes
class CShapeOne
{
public:
virtual void Draw() = 0;
protected:
CDrawLibOne m_lib;
};
// CCircleOne and CRectangleOne class are derived from CShape class.
// They use CDrawLibOne to draw.
class CCircleOne : public CShapeOne
{
void Draw() {m_lib.DrawCircle();}
};
class CRectangleOne : public CShapeOne
{
void Draw() {m_lib.DrawRectangle();}
};
// CShapeTwo class use library 2 to draw shapes
class CShapeTwo
{
public:
virtual void Draw() = 0;
protected:
CDrawLibTwo m_lib;
};
// CCircleOne and CRectangleOne class are derived from CShape class.
// They use CDrawLibOne to draw.
class CCircleTwo : public CShapeTwo
{
void Draw() {m_lib.DrawCircle();}
};
class CRectangleTwo : public CShapeTwo
{
void Draw() {m_lib.DrawRectangle();}
};
// Define two global functions to draw with CShapeOne and CShapeTwo
void DrawOne(CShapeOne &s)
{
s.Draw();
}
void DrawTwo(CShapeTwo &s)
{
s.Draw();
}
// The client use above classes to draw
int main()
{
CCircleOne c1;
CCircleTwo c2;
CRectangleOne r1;
CRectangleTwo r2;
DrawOne(c1);
DrawOne(r1);
DrawTwo(c2);
DrawTwo(r2);
return 1;
}
用Bridge模式来实现,就简单清晰了,并且易于扩展。Bridge模式最重要就是把表示和实现分开。结构图如下:

#include <iostream>
#include “stdafx.h”
using namespace std;
// Draw with library 1
class CDrawLibOne
{
public:
void DrawCircle(){cout << “Draw circle with lib one” << endl;}
void DrawRectangle() {cout << “Draw rectangle with lib one” << endl;}
};
// Draw with library 2
class CDrawLibTwo
{
public:
void DrawCircle(){cout << “Draw circle with lib two” << endl;}
void DrawRectangle() {cout << “Draw rectangle with lib two” << endl;}
};
// Implementation interface for CShape
class CShapeImp
{
public:
virtual void DrawCircle() = 0;
virtual void DrawRectangle() = 0;
};
// Use Lib one to draw.
Class CShapeImpOne: public CShapeImp
{
public:
virtual void DrawCircle() {m_lib.DrawCircle();}
virtual void DrawRectangle() {m_lib.DrawRectangle();}
private:
CDrawLibOne m_lib;
};
// Use Lib two to draw.
Class CShapeImpTwo : public CShapeImp
{
public:
virtual void DrawCircle() {m_lib.DrawCircle();}
virtual void DrawRectangle() {m_lib.DrawRectangle();}
private:
CDrawLibTwo m_lib;
};
class CShape
{
public:
virtual void Draw() = 0;
protected:
CShapeImp * m_Imp;
};
class CCircle : public CShape
{
public:
CCircle(CShapeImp * imp) {m_Imp = imp;}
Virtual void Draw(){m_Imp->DrawCircle();}
};
class CRectangle : public CShape
{
public:
CRectangle(CShapeImp * imp) {m_Imp = imp;}
Virtual void Draw() {m_Imp->DrawRectangle();}
};
// Start Drawing
void main()
{
CShapeImpOne sImp1;
CShapeImpTwo sImp2;
// Draw with the Library 1
CCircle c1(&sImp1);
CRectangle r1(&sImp1);
C1.Draw();
R1.Draw();
// Draw with the Library 2
CCircle c2(&sImp2);
CRectangle r2(&sImp2);
C2.Draw();
R2.Draw();
Return;
}
#include “stdafx.h”
using namespace std;
// Draw with library 1
class CDrawLibOne
{
public:
void DrawCircle(){cout << “Draw circle with lib one” << endl;}
void DrawRectangle() {cout << “Draw rectangle with lib one” << endl;}
};
// Draw with library 2
class CDrawLibTwo
{
public:
void DrawCircle(){cout << “Draw circle with lib two” << endl;}
void DrawRectangle() {cout << “Draw rectangle with lib two” << endl;}
};
// Implementation interface for CShape
class CShapeImp
{
public:
virtual void DrawCircle() = 0;
virtual void DrawRectangle() = 0;
};
// Use Lib one to draw.
Class CShapeImpOne: public CShapeImp
{
public:
virtual void DrawCircle() {m_lib.DrawCircle();}
virtual void DrawRectangle() {m_lib.DrawRectangle();}
private:
CDrawLibOne m_lib;
};
// Use Lib two to draw.
Class CShapeImpTwo : public CShapeImp
{
public:
virtual void DrawCircle() {m_lib.DrawCircle();}
virtual void DrawRectangle() {m_lib.DrawRectangle();}
private:
CDrawLibTwo m_lib;
};
class CShape
{
public:
virtual void Draw() = 0;
protected:
CShapeImp * m_Imp;
};
class CCircle : public CShape
{
public:
CCircle(CShapeImp * imp) {m_Imp = imp;}
Virtual void Draw(){m_Imp->DrawCircle();}
};
class CRectangle : public CShape
{
public:
CRectangle(CShapeImp * imp) {m_Imp = imp;}
Virtual void Draw() {m_Imp->DrawRectangle();}
};
// Start Drawing
void main()
{
CShapeImpOne sImp1;
CShapeImpTwo sImp2;
// Draw with the Library 1
CCircle c1(&sImp1);
CRectangle r1(&sImp1);
C1.Draw();
R1.Draw();
// Draw with the Library 2
CCircle c2(&sImp2);
CRectangle r2(&sImp2);
C2.Draw();
R2.Draw();
Return;
}
6, 总结
未使用Bridge模式的结构中,所有的类都处于一维空间,在同一条轴线上。要用哪个库来画哪个图形,用函数表示就是:Draw = f(Shape);

使用Bridge模式结构中,把变化的部分和不变的部分分别列在两个正交的坐标轴上,形成二维坐标系统。在随机系统中,正交的两个序列相关性最小。因此,Bridge模式就剥离了实现和表现。用函数表示为:Draw = f(Shape, Imp)

7, 相关模式
Abstract Factory模式可以用来创建和配置一个特定的Bridge模式
Adapter模式用来帮助无关的类协同工作,它通常在系统设计完成后才会被使用;Bridge模式则是在系统开始时就被使用,它使得抽象接口和实现部分可以独立进行改变。