Bridge Mode ):
Definition: decouples abstraction from its implementation so that they can all change independently. (Note: The implementation here refers to the abstract class and its derived classes used to implement their own objects)
Implementation: encapsulate the implementation in an abstract class. Contains an implementation handle in the abstract base class to be implemented.
Structure:
The implementation action is the object interface to be implemented, and the Implementor is the specific implementation class interface. The derived class of the role Action uses the class of Implementor, but you do not need to know which ConcreteImplementor you are using.
Sample Code:
Consider this software requirement: You need to write a program that uses one of two plotting programs (DP1 and DP2) to draw a rectangle and a circle.
First, define implementation. Drawing is the implementation base class. V1Drawing and V2Drawing are child classes of Drawing. V1Drawing uses the Drawing program DP1 to draw lines and circles. V2Drawing uses the Drawing program DP2 to draw lines and circles.
1 public abstract class Drawing { 2 public abstract void DrawLine(double x1, double y1, double x2, double y2); 3 public abstract void DrawCircle(double x, double y, double r); 4 } 5 6 public class V1Drawing : Drawing { 7 public override void DrawLine(double x1, double y1, double x2, double y2) { 8 dp1.DrawLine(x1, y1, x2, y2); 9 }10 11 public override void DrawCircle(double x, double y, double r) {12 dp1.DrawCircle(x, y, r);13 }14 15 private DP1 dp1 = new DP1();16 }17 18 public class V2Drawing : Drawing {19 public override void DrawLine(double x1, double y1, double x2, double y2) {20 dp2.DrawLine(x1, y1, x2, y2);21 }22 23 public override void DrawCircle(double x, double y, double r) {24 dp2.DrawCircle(x, y, r);25 }26 27 private DP2 dp2 = new DP2();28 }
Then define the abstraction, that is, the base class of the implemented object. Here is the base class of the rectangle and the circle (Sharp). In the Sharp, there is a Drawing handle that is passed in by the constructor, however, Sharp does not know the specific type of Drawing (V1Drawing or V2Drawing). This isolates abstraction and implementation (decoupling ).
1 public abstract class Sharp { 2 public Sharp(Drawing drawing) { 3 this.drawing = drawing; 4 } 5 6 public abstract void Draw(); 7 8 protected void DrawLine(double x1, double y1, double x2, double y2) { 9 this.drawing.DrawLine(x1, y1, x2, y2);10 }11 12 protected void DrawCircle(double x, double y, double r) {13 this.drawing.DrawCircle(x, y, r);14 }15 16 private Drawing drawing;17 }
The following is the abstract derived class,
1 public class Rectangle : Sharp { 2 public Rectangle(Drawing drawing, double x1, double y1, double x2, double y2) 3 : base(drawing) { 4 this.x1 = x1; 5 this.y1 = y1; 6 this.x2 = x2; 7 this.y2 = y2; 8 } 9 10 public override void Draw() {11 DrawLine(x1, y1, x2, y1);12 DrawLine(x2, y1, x2, y2);13 DrawLine(x1, y1, x1, y2);14 DrawLine(x1, y2, x1, y1);15 }16 17 private double x1, y1, x2, y2;18 }19 20 public class Circle : Sharp {21 public Circle(Drawing drawing, double x, double y, double r)22 : base(drawing) {23 this.x = x;24 this.y = y;25 this.r = r;26 }27 28 public override void Draw() {29 DrawCircle(x, y, r);30 }31 32 private double x, y, r;33 }
Finally, execute the program.
1 public class Client {2 static void Main(string[] args) {3 List<Sharp> sharps = new Factory().GetSharps();4 foreach(var each in sharps) {5 each.Draw();6 }7 }8 }
Summary:
Through the Bridge mode, abstraction and implementation can be decoupled and can be changed independently. For example, it is easy to add an elliptical shape or add a drawing program DP3.
At the same time, we should follow the basic policy to cope with changes: Find and encapsulate the changes; Prioritize object clustering rather than class inheritance.