桥接模式(Bridge)

首先分享关于桥接模式的一遍好文章; 研磨设计模式之桥接模式 https://www.oschina.net/question/1435262_140274

 

 桥接模式的定义是:将抽象部分和它的实现部分分离,使他们都可以独立的变化;关系如下图:

Abstraction

       抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。

RefinedAbstraction

       扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

Implementor

       定义实现部分的接口,这个接口不用和Abstraction里面的方法一致,通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

ConcreteImplementor

       真正实现Implementor接口的对象。

是不是看的一脸懵逼,不急,我们举个例子来分析一下:

 做我们这行的应该都玩过英雄联盟;游戏中地图分几种模式(如:大乱斗、匹配、排位);而且每种模式每个人都可以成一百多个英雄种选取一个,我们改如何应对这种多对多的关系呢?

按照以前的法我们肯定会采用继承,如下图:

代码如下:

//地图接口
public interface Ditu {
 public void run();
}
//大乱斗地图
public class DaLuandouDitu implements Ditu{

    public void run() {
        System.out.println("大乱斗地图");
        
    }

}
//匹配模式地图
public class PipeiDitu implements Ditu{

    public void run() {
    System.out.println("匹配模式地图");
        
    }

}
/德码 类
public class Dama extends DaLuandouDitu{
  public void run(){
      System.out.println("德码在大乱斗地图");
  }
}
public class Dema2 extends PipeiDitu{
     public void run(){
          System.out.println("德码在匹配地图");
      }
}
//寒冰省略

这种写法不仅代码混乱,关系复杂,重复的也多;而且扩展性也差;假设现在我要增一个英雄和一个模式,简直是一个噩梦;

我们用桥接模式来做:首先将抽象部分和它的实现部分分离;如下图:

代码如下:

实现部分

//英雄接口
public interface XYinterface {
public void run();
}
//英雄 德码 类
public class Dama implements XYinterface{
  public void run(){
      System.out.println("大宝剑德码");
  }
}
//英雄寒冰
public class HanBing implements XYinterface{
     public void run(){
          System.out.println("百步穿杨小寒冰");
      }
}

抽象部分:

//抽象部分
public abstract class AbstractDitu {
 protected XYinterface xYinterface;
 
public abstract void getDitu();
 
public XYinterface getxYinterface() {
    return xYinterface;
}

public void setxYinterface(XYinterface xYinterface) {
    this.xYinterface = xYinterface;
}
 
}
//大乱斗地图
public class DaLuandouDitu extends AbstractDitu{

    @Override
    public void getDitu() {
        xYinterface.run();
        System.out.println("在大乱斗地图");
        
    }

}
//匹配模式地图
public class PipeiDitu extends AbstractDitu{

    
    @Override
    public void getDitu() {
        xYinterface.run();
        System.out.println("在大乱斗地图");
            
    }

}

测试如下:

public class Test  {

    public static void main(String[] args) {

    XYinterface xYinterface=new HanBing();
    AbstractDitu ab=new PipeiDitu();
        ab.setxYinterface(xYinterface);
        ab.getDitu();
    }
}

输出

百步穿杨小寒冰
在匹配地图

在这种模式下新增一种模式或一种英雄就很简单了;只要实现相对的抽象接口即可;

认识桥接模式(来自分享博客)

(1)什么是桥接

       在桥接模式里面,不太好理解的就是桥接的概念,什么是桥接?为何需要桥接?如何桥接?把这些问题搞清楚了,也就基本明白桥接的含义了。

       一个一个来,先看什么是桥接?所谓桥接,通俗点说就是在不同的东西之间搭一个桥,让他们能够连接起来,可以相互通讯和使用。那么在桥接模式中到底是给什么东西来搭桥呢?就是为被分离了的抽象部分和实现部分来搭桥,比如前面示例中抽象的消息和具体消息发送之间搭个桥。

       但是这里要注意一个问题:在桥接模式中的桥接是单向的,也就是只能是抽象部分的对象去使用具体实现部分的对象,而不能反过来,也就是个单向桥。

(2)为何需要桥接

       为了达到让抽象部分和实现部分都可以独立变化的目的,在桥接模式中,是把抽象部分和实现部分分离开来的,虽然从程序结构上是分开了,但是在抽象部分实现的时候,还是需要使用具体的实现的,这可怎么办呢?抽象部分如何才能调用到具体实现部分的功能呢?很简单,搭个桥不就可以了,搭个桥,让抽象部分通过这个桥就可以调用到实现部分的功能了,因此需要桥接。

(3)如何桥接

       这个理解上也很简单,只要让抽象部分拥有实现部分的接口对象,这就桥接上了,在抽象部分就可以通过这个接口来调用具体实现部分的功能。也就是说,桥接在程序上就体现成了在抽象部分拥有实现部分的接口对象,维护桥接就是维护这个关系。

(4)独立变化

       桥接模式的意图:使得抽象和实现可以独立变化,都可以分别扩充。也就是说抽象部分和实现部分是一种非常松散的关系,从某个角度来讲,抽象部分和实现部分是可以完全分开的,独立的,抽象部分不过是一个使用实现部分对外接口的程序罢了。

       如果这么看桥接模式的话,就类似于策略模式了,抽象部分需要根据某个策略,来选择真实的实现,也就是说桥接模式的抽象部分相当于策略模式的上下文。更原始的就直接类似于面向接口编程,通过接口分离的两个部分而已。但是别忘了,桥接模式的抽象部分,是可以继续扩展和变化的,而策略模式只有上下文,是不存在所谓抽象部分的。

       那抽象和实现为何还要组合在一起呢?原因是在抽象部分和实现部分还是存在内部联系的,抽象部分的实现通常是需要调用实现部分的功能来实现的。

posted @ 2017-06-08 14:36  含笑V  阅读(363)  评论(0)    收藏  举报