在明白桥接模式之前需要先弄懂一个概念,聚合/组合原则。聚合和组合都是一种拥有关系,唯一不同的是,聚合中的主对象和附属对象可以独立存在,所以生命周期互不影响,而组合关系是依赖共生的,他们有共同的生命周期,一旦主对象不存在,附属对象也就没有了。举例:树和树叶是组合关系,一旦树枯死了,树叶也就不能存活了;车和车轮是聚合关系,车轮就算没有安装在汽车上一样可以存在。
桥接模式正是运用了聚合/组合原则来满足设计的需求,以达到抽象部分和它的实现部分分离,让他们都有自己的实现,从而达到松耦合的目的。
以一个例子说明桥接模式。比如这里存在一种手机模型,现在有很多种品牌和软件存在,现在要想在某种品牌手机上运行游戏或者音乐软件,如果用传统的继承方法来做,大概是这种模型:
这种模型确实可用,但是不利于扩展,如果现在要加入"小米手机"品牌或者加入一个新的手机功能模块,那么还要继续添加小米手机的品牌和相应的软件和游戏类。而新添加的功能和以前的代码功能差不多,这样做就没有达到代码复用的目的。因为这种继承关系,子类严重依赖父类,如果在现在手机加入新功能了,那么还必须修改父类才能达到添加功能的目的。
如果使用桥接模式设计的话,类图则会是以下的样子:
相应的的代码如下:
手机品牌具体实现类和手机抽象类:
1 public abstract class Phone { 2 3 public Soft soft; 4 5 public void setSoft(Soft soft){ 6 this.soft = soft; 7 } 8 9 public abstract void run(); 10 }
1 public class Nokia extends Phone { 2 @Override 3 public void run() { 4 soft.run(); 5 } 6 }
1 public class WinPhone extends Phone { 2 @Override 3 public void run() { 4 soft.run(); 5 } 6 }
手机软件抽象类和具体软件实现类:
1 public abstract class Soft { 2 public abstract void run(); 3 }
1 public class Game extends Soft { 2 @Override 3 public void run() { 4 System.out.println("ganme run……"); 5 } 6 }
1 public class Music extends Soft { 2 @Override 3 public void run() { 4 System.out.println("music run……"); 5 } 6 }
测试类如下:
1 public class Test { 2 public static void main(String[] args) { 3 Phone nokia = new Nokia(); 4 nokia.setSoft(new Game()); 5 nokia.run(); 6 7 nokia.setSoft(new Music()); 8 nokia.run(); 9 10 Phone winphone = new WinPhone(); 11 winphone.setSoft(new Game()); 12 winphone.run(); 13 14 winphone.setSoft(new Music()); 15 winphone.run(); 16 } 17 }
运行结果:
总结:桥接模式很大程度上解决了继承带来的代码不能复用和冗余问题,而且利于扩展,遵守了开闭原则。