语言与模式-11桥接模式
意图
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
适用性
- 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
- (C++)你想对客户完全隐藏抽象的实现部分。在C++中,类的表示在类接口中是可见的。
- 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。Rumbaugh称这种类层次结构为“嵌套的普化”(nested generalizations )。
- 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是Coplien的String类,在这个类中多个对象可以共享同一个字符串表示(StringRep)。
Java实现
//电视机的接口
public interface ITV {
public void on();
public void off();
public void switchChannel(int channel);
}
//三星的ITV
public class SamsungTV implements ITV {
@Override
public void on() {
System.out.println("Samsung is turned on.");
}
@Override
public void off() {
System.out.println("Samsung is turned off.");
}
@Override
public void switchChannel(int channel) {
System.out.println("Samsung: channel - " + channel);
}
}
//索尼的ITV
public class SonyTV implements ITV {
@Override
public void on() {
System.out.println("Sony is turned on.");
}
@Override
public void off() {
System.out.println("Sony is turned off.");
}
@Override
public void switchChannel(int channel) {
System.out.println("Sony: channel - " + channel);
}
}
//遥控器要包含对TV的引用
public abstract class AbstractRemoteControl {
private ITV tv;
public AbstractRemoteControl(ITV tv){
this.tv = tv;
}
public void turnOn(){
tv.on();
}
public void turnOff(){
tv.off();
}
public void setChannel(int channel){
tv.switchChannel(channel);
}
}
//定义遥控器的具体类
public class LogitechRemoteControl extends AbstractRemoteControl {
public LogitechRemoteControl(ITV tv) {
super(tv);
}
public void setChannelKeyboard(int channel){
setChannel(channel);
System.out.println("Logitech use keyword to set channel.");
}
}
//调用
public class Main {
public static void main(String[] args){
ITV tv = new SonyTV();
LogitechRemoteControl lrc = new LogitechRemoteControl(tv);
lrc.setChannelKeyboard(100);
}
}
Clojure实现
first-class function轻松解决!
三星命名空间:
(ns samsung)
(defn on []
(println "Samsung is turned on."))
(defn off []
(println "Samsung is turned off."))
(defn switch-channel [channel]
(println "Samsung: channel - " + channel))
索尼命名空间:
(ns sony)
(defn on []
(println "Sony is turned on."))
(defn off []
(println "Sony is turned off."))
(defn switch-channel [channel]
(println "Sony: channel - " + channel))
RemoteController:
(ns remotecontroller)
(defn turn-on [f]
(f))
(defn turn-off [f]
(f))
(defn set-channel [f arg]
(f arg))
直接调用:
(ns client
(:require [sony :as tv]
[remotecontroller :as c]))
(c/turn-on tv/on)
(c/set-channel tv/switch-channel 3)
(c/trun-off tv/off)
这么实现简直就是脱裤子放屁~~!
直接调用sony或samsung里的函数就行了!多此一举!