(learn&think)

不浮躁,不自傲,学习,思考,总结

浅谈设计模式十七: 桥接模式(Bridge)

| Comments

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)
    1. 定义抽象的接口。
    2. 维护一个指向实现类(Implementor)类型的对象的引用。
  • 精炼抽象类(Refined Abstraction)扩展抽象类定义的接口。
  • 抽象实现者(Implementor)为实现类定义接口。这个接口没有必要和抽象类(Abstraction)的接口相一致。实际上这两个接口可以很不同。典型的抽象实现类接口只提供原始操作,然而抽象类基于这些原始操作定义上层操作。
  • 具体实现类(ConcreteImplementor)实现抽象实现类(Implementor)接口。

3.3 应用场景

  • 当你想避免抽象部分和它的实现部分永久的绑定时。例如,可能这样的情况,当实现部分必须在运行时被选取或换出。
  • 抽象部分和它们的实现部分都需要能被子类扩展时。在这种情况,桥接模式让你组合不同的抽象部分和实现部分并可独立扩展它们。
  • 当改变抽象的实现部分对客户没有任何影响时,也就是,客户的代码不需要重新编译。
  • (C++)你想从客户那完全隐藏抽象的实现部分.在 C++中,类的表现在类的接口里可以看到。
  • 你有一堆激增的类时。如此类的层次表明需要把对象分离成两部分。
  • 当你想在多个对象见共享一个实现部分(可能使用引用计数),并想把这个事实从客户那隐藏掉时。

Comments