Bridge模式,又叫桥接模式,是针对同一接口进行扩展与实现操作的一种设计模式。
这种模式,与之前学过的适配器模式具有相似的地方,也有不同的地方,下面就让我们一一解析吧。
首先,我们要了解到,为什么需要使用Bridge模式:
现在有一个抽象类/接口,这个抽象类是起到了一个规范的作用,规范一些方法。
示例是用来在控制台中打印输出框和字符串(规范输出)
- DisplayImpl 抽象类,规范了打印的方法
package site.wangxin520.gof.bridge; /** * 原先需要实现/继承的类/接口 * @author wangXgnaw * */ public abstract class DisplayImpl { //打开输出框 public abstract void rawOpen(); //在输出框里面打印字符串 public abstract void rawPrint(); //当打印字符串结束后,关闭输出框 public abstract void rawClose(); }
在此抽象类/当然也可以使用接口中,规定了三个抽象方法,让子类去实现具体的逻辑。
- StringDisplayImpl类,这个类是用来实现DisplayImpl中的抽象方法逻辑的。
package site.wangxin520.gof.bridge; /** * 继承了根类,并且重写了/实现了根类中定义的方法 * @author wangXgnaw * */ public class StringDisplayImpl extends DisplayImpl{ private String string; private int width; /** * 构造方法,传入需要规范/美化的字符串 * @param string 需要字符串 */ public StringDisplayImpl(String string) { this.string=string; this.width=string.length(); } /** * 实现父类的抽象方法,下同 */ @Override public void rawOpen() { System.out.print("+"); for (int i = 0; i < width; i++) { System.out.print("-"); } System.out.println("+"); } @Override public void rawPrint() { System.out.println("|"+string+"|"); } @Override public void rawClose() { System.out.print("+"); for (int i = 0; i < width; i++) { System.out.print("-"); } System.out.println("+"); System.out.println("*************************"); } }
在这个子类中,重写了父类中规定的抽象方法。根据面向对象的程序开发原则可知:
代码对扩展开放,但对于修改闭源。
所以,我们想要扩展功能的话,都是利用继承父类,然后在子类里面去新建方法的这种模式,但这里就得注意了,我们刚开始是实现了抽象类/接口,而规定接口/抽象类就是为了去有不同的实现逻辑,而如果再去扩展的话,就只是针对某一逻辑进行扩展,如果去扩展其他实现逻辑的话,就只能采用再去重写父类的抽象方法,再去继承来扩展。
因此,我们想到的是吧抽象类或者接口的具体实现和扩展分开来以达到扩展功能不影响实现,增加实现又不影响扩展的功能,这样就大大的简化了我们的开发。这种思想就是桥接的思想,也就是使用了bridge模式。
桥接模式和适配器模式的区别也就在此:
- 首先是两者的目的不同,桥接是为了分离接口的功能扩展和抽象方法的实现,而适配器模式是为了对同一实现提供不同接口。
- 其次是二者的实现方式不同,桥接是利用新接口去继承原先的旧接口,以此来提供新的接口给新的实现类,而桥接并不是为了改变接口,而是去为原来的接口增加功能。
下面就是具体的代码实现bridge模式:
- Display 在这个类里面,准备一个DisplayImpl抽象类的对象作为属性(利用多态,可以不用关注具体是抽象方法的哪种实现)。
package site.wangxin520.gof.bridge; /** * 桥接用,实现功能的类 * @author wangXgnaw * */ public class Display { /** * 准备一个属性,并且在构造Display类的时候将具体实现接口的类进行传入 */ private DisplayImpl impl; public Display(DisplayImpl impl){ this.impl=impl; } /** * 扩展了原抽象方法的方法,这里就类似于适配器模式 */ public void open(){ impl.rawOpen(); } public void print(){ impl.rawPrint(); } public void close(){ impl.rawClose(); } /** * 扩展了display方法 */ public final void display(){ open(); print(); close(); } }
- CountDisplay,扩展父类的方法
package site.wangxin520.gof.bridge; /** * 继承了Display类,继续扩展方法 * @author wangXgnaw * */ public class CountDisplay extends Display{ /** * 利用构造,传参,与父类相同 * @param impl */ public CountDisplay(DisplayImpl impl) { super(impl); } /** * 继续扩展了父类的方法 * @param times */ public void multiDisplay(int times){ open(); for (int i = 0; i < times; i++) { print(); } close(); } }
- 测试类:
package site.wangxin520.gof.bridge; /** * 桥接模式的测试类 * @author wangXgnaw * */ public class Test { public static void main(String[] args) { //d1和d2都是使用了默认的display方法 Display d1=new Display(new StringDisplayImpl("Hello world")); d1.display(); Display d2=new CountDisplay(new StringDisplayImpl("Hello mars")); d2.display(); //d3使用的是扩展出来的multiDisplay方法,因为父类是不能找到子类的专属方法,所以这里没有采用多态的方式 CountDisplay d3=new CountDisplay(new StringDisplayImpl("Hello moon")); d3.display(); d3.multiDisplay(3); } }
- 结果
可见,最后d3扩展出来的multiDisplay是可以展示的。