Chinaunix首页 | 论坛 | 博客
  • 博客访问: 817948
  • 博文数量: 62
  • 博客积分: 526
  • 博客等级: 二等列兵
  • 技术积分: 2078
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-04 20:41
个人简介

博客迁移至 freefe.cc

文章分类

全部博文(62)

分类: JavaScript

2013-12-25 11:56:46


桥接模式


    桥接模式是软件设计模式中最复杂的设计模式之一。需要将事物的对象和具体的行为,具体特征分离开来,使其可以各自独立的变化。桥接模式则在中间起类似于总调控的作用。

    事物对象是一个较为抽象的概念,如‘圆形’,‘三角形’归于抽象的‘形状’之下,‘画圆形’和‘画三角形’则归于具体行为的‘画图’之下,然后‘形状’这个抽象可以调用‘画图’行为方法。

    具体代码示例(来自维基百科):
    下语言的代码用于写出两个不同的圆的坐标和半径。

API1.circle at 1:2 7.5
API2.circle at 5:7 27.5


  1. /** "Implementor" */
  2. interface DrawingAPI
  3. {
  4.     public void drawCircle(double x, double y, double radius);
  5. }
  6.  
  7. /** "ConcreteImplementor" 1/2 */
  8. class DrawingAPI1 implements DrawingAPI
  9. {
  10.    public void drawCircle(double x, double y, double radius)
  11.    {
  12.         System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
  13.    }
  14. }
  15.  
  16. /** "ConcreteImplementor" 2/2 */
  17. class DrawingAPI2 implements DrawingAPI
  18. {
  19.    public void drawCircle(double x, double y, double radius)
  20.    {
  21.         System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
  22.    }
  23. }
  24.  
  25. /** "Abstraction" */
  26. interface Shape
  27. {
  28.    public void draw(); // low-level
  29.    public void resizeByPercentage(double pct); // high-level
  30. }
  31.  
  32. /** "Refined Abstraction" */
  33. class CircleShape implements Shape
  34. {
  35.    private double x, y, radius;
  36.    private DrawingAPI drawingAPI;
  37.    public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI)
  38.    {
  39.        this.x = x; this.y = y; this.radius = radius;
  40.        this.drawingAPI = drawingAPI;
  41.    }
  42.  
  43.    // low-level i.e. Implementation specific
  44.    public void draw()
  45.    {
  46.         drawingAPI.drawCircle(x, y, radius);
  47.    }
  48.    // high-level i.e. Abstraction specific
  49.    public void resizeByPercentage(double pct)
  50.    {
  51.         radius *= pct;
  52.    }
  53. }
  54.  
  55. /** "Client" */
  56. class BridgePattern {
  57.    public static void main(String[] args)
  58.    {
  59.        Shape[] shapes = new Shape[2];
  60.        shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
  61.        shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
  62.  
  63.        for (Shape shape : shapes)
  64.        {
  65.            shape.resizeByPercentage(2.5);
  66.            shape.draw();
  67.        }
  68.    }
  69. }



JS中的桥接模式


    简单的桥接模式,无非就是在设计API的时候可以弱化对象间(对象与类)的耦合程度。


  1. function sendInfo( element ){
  2.     var id = element.id;
  3.     ajax( "GET","info.json?id="+id, function( result ){
  4.          ...
  5.     });
  6.      ...
  7. }

     然后我们在很多地方或者事件中使用了sendInfo的方法,但是很明显该方法内部的 ajax 请求和整体的实现“性质”不太一样,那么将 ajax 请求方法独立出来,创建一个桥接与 ajax 和 回调函数以及其他代码运行的函数,就可以使整体的结构更加清晰合理,降低原有函数内部方法之间调用的耦合度。

    那么就需要对他的结构使用最简单的桥接模式的处理下

  1. function sendInfo( element ){
  2.     var id = element.id,
  3.     callback = function( result ){
  4.       // ...
  5.     }
  6.     sendInfoBridge( id, callback);
  7.    // ...
  8. }

  9. function sendInfoBridge( id, callback){
  10.     ajax( "GET","info.json?id="+id, function( result ){
  11.         callback( result );
  12.     });
  13.     // ...
  14. }

    那么简单的处理后 从结构上来说变得更为清晰,使得 sendInfo 中的部分方法脱离出来形成独立的方法。此处桥接可以看为 ajax 请求 与 id,callback 等的桥接。


桥接模式联结多个类


  1. var Class1 = function( a, b, c ){
  2.     this.a = a;
  3.     this.bc = b*c;
  4. }
  5. var Class2 = function( d ){
  6.     this.d = d;
  7. }

  8. function BridgeClass(a, b, c, d){
  9.     this.class1 = new Class1(a, b, c);
  10.     this.class2 = new Class2(d);
  11. }


    但是 在此的作用并没有降低耦合度什么的,反而使新创建的构造函数依赖于之前的构造函数 Class1 和 Class2,超级类似于门面模式?

    其实还是因为这里的实例太过于简单,简单来说,Class1 和 Class2 就是两个“性质”不一样的类,相当于最上面 维基百科 代码示例中的 shape 和 DrawingAPI, 而 BridgeClass 是将两个类联结在一起,使得 shape 可以调用 DrawingAPI 的中间桥接。也不用认为是依赖于之前的构造函数 Class1 和 Class2 因为本身就是实现两者,视为两代码从主程序中独立出来而并非依赖。

    该方式与适配器模式和门面模式(外观模式)都有点相似,不过
        与适配器模式不同之处 : 没有要求客户提供适配的数据。可以视为一种包装器,对接口进行适配以保证不同环境中兼容。
        与门面模式不同之处 : 门面模式仅仅是提供一个简化的接口供客户使用,提供一个高级接口使得子系统更容易使用。而桥接模式中 Class1 和 Class2 是能独立于 BridgeClass 发生改变的,门面模式却不同。

    在很多时候,我们会发现可能一些代码构建的太不合理,过于复杂,明明有更简单的方式来处理逻辑。但是也许是我们没有看到这样的处理方式代码的整体的影响。在此不举一些很复杂的例子,因为往往复杂的牛逼哄哄的例子往往都没啥心情学习与了解。


参考资料:
    1. 维基百科-桥接模式  
    2.《JS设计模式》


阅读(4286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~