1 实例
画圆可以顺时针或逆时针,但只能使用一种方法,不能同时既顺时针又逆时针。比较直观的做法就是定义两种不同的圆,但同时继承于圆的基本特性基类。但如果不采用继承并在运行时选取画圆的方法呢?
2 桥接模式(Bridge)
2.1 目的
从对象的具体实现中解藕出抽象部分,使它们可以各自独立的变化。
2.2 实现
把顺时针和逆时针的画法抽取出来成为独立的实现者类,由圆运行时可以选取自己的画法。代码实例在这里。
2.2.1 定义实现者抽象接口
class Drawing { public: virtual ~Drawing() {} virtual void drawCircle(double x, double y, double radius) = 0; };
2.2.2 顺时针实现类
class DrawingClockwise : public Drawing { public: virtual ~DrawingClockwise() {} virtual void drawCircle(double x, double y, double radius) { printf("draw the circle at %f,%f, radius %f by clockwise\n", x, y, radius); } };
2.2.3 逆时针实现类
class DrawingCounterClockwise : public Drawing { public: virtual ~DrawingCounterClockwise() {} virtual void drawCircle(double x, double y, double radius) { printf("draw the circle at %f,%f, radius %f by counter clockwise\n", x, y, radius); } };
2.2.4 圆类
维护一个实现者的实例并使用它完成相应的行为。
class CircleShape : public Shape { public: virtual ~CircleShape(); CircleShape(double x, double y, double radius, Drawing *drawing); virtual void draw(); virtual void resizeByPercentage(double pct); private: double x_; double y_; double radius_; Drawing *drawing_; }; void CircleShape::draw() { drawing_->drawCircle(x_, y_, radius_); }
3 总结
3.1 桥接模式(Bridge)结构
3.2 组成
- 抽象类(Abstraction)
- 定义抽象的接口。
- 维护一个指向实现类(Implementor)类型的对象的引用。
- 精炼抽象类(Refined Abstraction)扩展抽象类定义的接口。
- 抽象实现者(Implementor)为实现类定义接口。这个接口没有必要和抽象类(Abstraction)的接口相一致。实际上这两个接口可以很不同。典型的抽象实现类接口只提供原始操作,然而抽象类基于这些原始操作定义上层操作。
- 具体实现类(ConcreteImplementor)实现抽象实现类(Implementor)接口。
3.3 应用场景
- 当你想避免抽象部分和它的实现部分永久的绑定时。例如,可能这样的情况,当实现部分必须在运行时被选取或换出。
- 抽象部分和它们的实现部分都需要能被子类扩展时。在这种情况,桥接模式让你组合不同的抽象部分和实现部分并可独立扩展它们。
- 当改变抽象的实现部分对客户没有任何影响时,也就是,客户的代码不需要重新编译。
- (C++)你想从客户那完全隐藏抽象的实现部分.在 C++中,类的表现在类的接口里可以看到。
- 你有一堆激增的类时。如此类的层次表明需要把对象分离成两部分。
- 当你想在多个对象见共享一个实现部分(可能使用引用计数),并想把这个事实从客户那隐藏掉时。