当我们的功能要在多个维度进行扩展时,各个维度之间可以交叉组合,就可以考虑使用桥接模式。
将抽象部分与实现部分分离,使它们都可以独立的变化。
——《设计模式》GOF
我们看一个实际的例子来理解:
我想发一条短信,首先,我要选择使用哪一种信号(联通、移动、电信);其次,我们要选择发送的内容(文本、附件、音频);最后,我们要选择发送的时间(实时、定时)。
那么,这里有三个维度的变化,每个维度有3、3、2种类型,如果我们使用传统的继承的方式来扩展一个类的功能,那么我们需要一个顶级短信发送类,3种信号类都去继承这个顶级类,3种内容类去继承每一种信号类,2种发送时间类再去继承每一种内容类。
这样我们得到了3*3*2+1=19个类(或者不要顶级类,得到18个类),如果再有其他的扩展维度进来的话,类的个数将不堪设想。
这时我们就可以考虑使用桥接模式,使各个扩展维度之间解耦,使它们相互独立。每个变化的维度都可以抽象成统一的类,由这个维度变化的子类去进行扩展。而各个维度的抽象类之间,可以相互持有各自的引用,从而拥有其他维度的功能。
各个变化维护的抽象类:
public abstract class Message { private String content; abstract public void send(); public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
public abstract class Signal { protected Message msg; public abstract void invoke(); }
各个维度变化的子类:
public class TextMessage extends Message { @Override public void send() { System.out.println("发送【文字】信息:" + this.getContent()); } }
public class PicMessage extends Message { @Override public void send() { System.out.println("发送【图片】信息:" + this.getContent()); } }
public class AudioMessage extends Message { @Override public void send() { System.out.println("发送【语音】信息:" + this.getContent()); } }
public class YiDongSignal extends Signal { public YiDongSignal(Message msg) { super(); this.msg = msg; } @Override public void invoke() { System.out.print("使用【移动】:"); msg.send(); } }
public class LianTongSignal extends Signal { public LianTongSignal(Message msg) { super(); this.msg = msg; } @Override public void invoke() { System.out.print("使用【联通】:"); msg.send(); } }
public class DianXinSignal extends Signal { public DianXinSignal(Message msg) { super(); this.msg = msg; } @Override public void invoke() { System.out.print("使用【电信】:"); msg.send(); } }
客户端调用:
public class Client { public static void main(String[] args) { Message msg = new TextMessage(); msg.setContent("Hello World!"); Signal signal = new YiDongSignal(msg); signal.invoke(); } }
输出结果:
使用【移动】:发送【文字】信息:Hello World!
上面只扩展了两个维度,如果现在我们要扩展第三个维度--发送时间的话,就可以简单的加几个类就行了:
变化维度抽象类:
public abstract class SendTime { protected Signal signal; abstract public void sendMsg(); }
变化维度子类:
public class InstantSendTime extends SendTime{ public InstantSendTime(Signal signal) { super(); this.signal = signal; } @Override public void sendMsg() { System.out.print("【实时发送】-->"); this.signal.invoke(); } }
客户端调用:
public class Client2 { public static void main(String[] args) { Message msg = new TextMessage(); msg.setContent("Hello World!"); Signal signal = new YiDongSignal(msg); SendTime sendTime = new InstantSendTime(signal); sendTime.sendMsg(); } }
输出结果:
【实时发送】-->使用【移动】:发送【文字】信息:Hello World!
细心的读者不难发现,在我们客户端调用的时候,有点像Decorator装饰模式。
但它和Decorator是有区别的,Bridge是从多个维度扩展,而Decorator是将多个包装类的功能加在一起,组合成一个多功能的类。(描述不太清楚,后续修改)