当我们的功能要在多个维度进行扩展时,各个维度之间可以交叉组合,就可以考虑使用桥接模式。
将抽象部分与实现部分分离,使它们都可以独立的变化。
——《设计模式》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是将多个包装类的功能加在一起,组合成一个多功能的类。(描述不太清楚,后续修改)
可以再看看Decorator装饰模式自己体味区别