JS设计模式三:桥接模式
2013-12-25 11:56:46
分类: JavaScript
桥接模式
桥接模式是软件设计模式中最复杂的设计模式之一。需要将事物的对象和具体的行为,具体特征分离开来,使其可以各自独立的变化。桥接模式则在中间起类似于总调控的作用。
事物对象是一个较为抽象的概念,如‘圆形’,‘三角形’归于抽象的‘形状’之下,‘画圆形’和‘画三角形’则归于具体行为的‘画图’之下,然后‘形状’这个抽象可以调用‘画图’行为方法。
具体代码示例(来自维基百科):
下语言的代码用于写出两个不同的圆的坐标和半径。
API1.circle at 1:2 7.5 API2.circle at 5:7 27.5
- /** "Implementor" */
- interface DrawingAPI
- {
- public void drawCircle(double x, double y, double radius);
- }
-
- /** "ConcreteImplementor" 1/2 */
- class DrawingAPI1 implements DrawingAPI
- {
- public void drawCircle(double x, double y, double radius)
- {
- System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
- }
- }
-
- /** "ConcreteImplementor" 2/2 */
- class DrawingAPI2 implements DrawingAPI
- {
- public void drawCircle(double x, double y, double radius)
- {
- System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
- }
- }
-
- /** "Abstraction" */
- interface Shape
- {
- public void draw(); // low-level
- public void resizeByPercentage(double pct); // high-level
- }
-
- /** "Refined Abstraction" */
- class CircleShape implements Shape
- {
- private double x, y, radius;
- private DrawingAPI drawingAPI;
- public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI)
- {
- this.x = x; this.y = y; this.radius = radius;
- this.drawingAPI = drawingAPI;
- }
-
- // low-level i.e. Implementation specific
- public void draw()
- {
- drawingAPI.drawCircle(x, y, radius);
- }
- // high-level i.e. Abstraction specific
- public void resizeByPercentage(double pct)
- {
- radius *= pct;
- }
- }
-
- /** "Client" */
- class BridgePattern {
- public static void main(String[] args)
- {
- Shape[] shapes = new Shape[2];
- shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
- shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
-
- for (Shape shape : shapes)
- {
- shape.resizeByPercentage(2.5);
- shape.draw();
- }
- }
- }
JS中的桥接模式
简单的桥接模式,无非就是在设计API的时候可以弱化对象间(对象与类)的耦合程度。
- function sendInfo( element ){
- var id = element.id;
- ajax( "GET","info.json?id="+id, function( result ){
- ...
- });
- ...
- }
然后我们在很多地方或者事件中使用了sendInfo的方法,但是很明显该方法内部的 ajax 请求和整体的实现“性质”不太一样,那么将 ajax 请求方法独立出来,创建一个桥接与 ajax 和 回调函数以及其他代码运行的函数,就可以使整体的结构更加清晰合理,降低原有函数内部方法之间调用的耦合度。
那么就需要对他的结构使用最简单的桥接模式的处理下
- function sendInfo( element ){
- var id = element.id,
- callback = function( result ){
- // ...
- }
- sendInfoBridge( id, callback);
- // ...
- }
- function sendInfoBridge( id, callback){
- ajax( "GET","info.json?id="+id, function( result ){
- callback( result );
- });
- // ...
- }
那么简单的处理后 从结构上来说变得更为清晰,使得 sendInfo 中的部分方法脱离出来形成独立的方法。此处桥接可以看为 ajax 请求 与 id,callback 等的桥接。
桥接模式联结多个类
- var Class1 = function( a, b, c ){
- this.a = a;
- this.bc = b*c;
- }
- var Class2 = function( d ){
- this.d = d;
- }
- function BridgeClass(a, b, c, d){
- this.class1 = new Class1(a, b, c);
- this.class2 = new Class2(d);
- }
但是 在此的作用并没有降低耦合度什么的,反而使新创建的构造函数依赖于之前的构造函数 Class1 和 Class2,超级类似于门面模式?
其实还是因为这里的实例太过于简单,简单来说,Class1 和 Class2 就是两个“性质”不一样的类,相当于最上面 维基百科 代码示例中的 shape 和
DrawingAPI,
而 BridgeClass 是将两个类联结在一起,使得 shape 可以调用
DrawingAPI 的中间桥接。也不用认为是
依赖于之前的构造函数 Class1 和 Class2 因为本身就是实现两者,视为两代码从主程序中独立出来而并非依赖。
该方式与适配器模式和门面模式(外观模式)都有点相似,不过
与适配器模式不同之处
: 没有要求客户提供适配的数据。可以视为一种包装器,对接口进行适配以保证不同环境中兼容。
与门面模式不同之处
: 门面模式仅仅是提供一个简化的接口供客户使用,提供一个高级接口使得子系统更容易使用。
而桥接模式中
Class1 和 Class2 是能独立于
BridgeClass 发生改变的,门面模式却不同。
在很多时候,我们会发现可能一些代码构建的太不合理,过于复杂,明明有更简单的方式来处理逻辑。但是也许是我们没有看到这样的处理方式代码的整体的影响。在此不举一些很复杂的例子,因为往往复杂的牛逼哄哄的例子往往都没啥心情学习与了解。
参考资料:
2.《JS设计模式》