今天来学习一个很重要的设计模式---桥接模式。在了解桥接模式之前首先来学习面向对象的又一个重要原则,合成聚合复用原则。
合成聚合复用原则是说尽量使用合成聚合,而不使用继承。聚合表示一种弱的拥有关系比如雁群拥有大雁,而合成表示一种强的拥有关系比如大雁拥有翅膀。
现在具个例子来说明下合成聚合复用原则和继承对比的优点。假如有不同厂家的手机使用不同类型的软件,如果用继承的想法来做的话,我们肯定会写一个基类,手机,然后不同厂商的手机都继承这个基类,手机,,如Nokia手机。每种手机使用不同的软件,然后不同的软件再继承Nokia手机,如“Nokia手机Game”这样一个类。UML类图如下:
在这样一个类结构里面如果要新加一个手机类型或者手机软件的话就得新加至少两个类,这样代码的复用率不高。这个也正是继承的缺点,子类完全依赖父类,如果父类的需求有变化,则所有的子类都得重新写。在这里体现为新加一种手机型号。这种依赖关系违背了依赖倒转原则。但是如果我们对类图做如此修改:
那么新加一种手机品牌的话只用新加一个类就可以了,这个类图是把手机品牌和手机软家分开处理。也就是说以后在用到继承关系的时候一定先要考虑是否满足“is-a”关系,这里面手机品牌和手机软件明显不满足,他们应该是属于聚合关系,即手机品牌弱拥有手机软件。如果有这样的关系哪么我们就一定要考虑合成聚合原则了。
由于这个类图中间的聚合线看起来很像一做桥把他们联系起来。所以这种设计模式称为桥接模式。
桥接模式是指让抽象部分与实现部分分离,使它们都可以独立的变化。通俗来讲就是实现系统可能有多角度分类,没一种分类都有可能变化,哪么就把这种多角度分离出来,让他们独立的变化,减少他们之间的耦合。
下面通过代码让我们来熟悉下这种设计模式。
首先是手机品牌的那个分支:
package darren.designmodel.bridge; public abstract class TelBrand { protected TelSoftWare soft; public void setSoft(TelSoftWare sof){ this.soft = sof; } abstract void runSoft(); }
public class NokiaBrand extends TelBrand{ @Override void runSoft() { // TODO Auto-generated method stub soft.run("Nokia"); } } public class HTCBrand extends TelBrand{ @Override void runSoft() { // TODO Auto-generated method stub soft.run("HTC"); } }
其次是手机软件的那一类分支:
public abstract class TelSoftWare { public abstract void run(String brand); } public class GameSoft extends TelSoftWare { @Override public void run(String brand) { // TODO Auto-generated method stub System.out.println("running the GameSoft on " + brand + " cellPhone."); } } public class ContactSoft extends TelSoftWare{ @Override public void run(String brand) { // TODO Auto-generated method stub System.out.println("running the ContactSoft on " + brand + " cellPhone."); } }
这里手极软件有游戏和通讯录2种,对于不同的手机型号会有不同的处理,测试代码如下:
public static void main(String[] args) { // TODO Auto-generated method stub TelBrand tb = new NokiaBrand(); tb.setSoft(new GameSoft()); tb.runSoft(); tb = new HTCBrand(); tb.setSoft(new ContactSoft()); tb.runSoft(); }
最后的运行结果为:
running the GameSoft on Nokia cellPhone. running the ContactSoft on HTC cellPhone.
这样就做到了不同手机软件不同手机型号的不同处理。
桥接模式介绍完毕,感谢大家的关注。