甜蜜的家庭影院
在进入外观模式的细节之前,让我们看一个风行全球的热潮:建立自己的家庭影院。
通过一番比较,你组装了一套杀手级的系统,内涵DVD播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。
你花了好几个星期布线、挂上投影机、链接所有的装置并进行微调。现在,你准备开始享受一部电影……
观赏电影(用困难的方式)
挑选一部DVD影片,放松,准备开始感受电影的魔幻魅力。哎呀!忘了一件事:想看电影,必须要先执行一些任务:
- 打开爆米花机
- 开始爆米花
- 将灯光调暗
- 放下屏幕
- 打开投影机
- 将投影机的输入切换到DVD
- 将投影机设置到宽屏模式
- 打开功放
- 将功放的输入设置为DVD
- 将功放设置为环绕立体声
- 将功放音量设置到百分之五十
- 打开DVD播放器
- 开始播放DVD
让我们将这些任务写成类和方法的调用:
public class Client {
public static void main(String[] args) {
// 打开爆米花机
Popper popper = new Popper();
popper.on();
popper.pop();
// 调暗灯光
Lights lights = new Lights();
lights.dim(10);
// 设置屏幕
Screen screen = new Screen();
screen.down();
// 设置投影机
Projector projector = new Projector();
projector.on();
projector.setInput("Dvd");
projector.wideScreenMode();
// 设置功放
Amp amp = new Amp();
amp.on();
amp.setDvd();
amp.setSurroundSound();
amp.setVolume(5);
// 开始看电影
Dvd dvd = new Dvd();
dvd.play();
}
}
整个一个调用过程涉及到了六个类,但还不止如此,看完后还需要把一切都关掉……如果想要切换到CD或者听广播怎么办?如果要升级系统,可能还需要重新学习一下稍微不同的操作过程……
使用你的家庭影院竟然变得如此复杂!让我们看看外观模式如何解决这团混乱,好让你能轻松地享受电影……
外观模式
你需要的正是一个外观,有了外观模式,通过实现一个提供更合理的接口的外观类,你可以将一个复杂的子系统变得容易使用。如果你需要复杂的子系统的强大威力,别担心,还是可以使用原来的复杂接口的,但如果你需要的是一个方便使用的接口,那就使用外观模式吧!
让我们看看外观模式如何运作:
package cn.net.bysoft.facade;
public class HomeTheaterFacade {
Popper popper;
Lights lights;
Screen screen;
Projector projector;
Amp amp;
Dvd dvd;
public HomeTheaterFacade(Popper popper, Lights lights, Screen screen, Projector projector, Amp amp, Dvd dvd) {
this.popper = popper;
this.lights = lights;
this.screen = screen;
this.projector = projector;
this.amp = amp;
this.dvd = dvd;
}
public void watchMovie() {
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.setInput("Dvd");
projector.wideScreenMode();
amp.on();
amp.setDvd();
amp.setSurroundSound();
amp.setVolume(5);
dvd.play();
}
}
观赏电影(用轻松的方式)
package cn.net.bysoft.facade;
public class Client {
public static void main(String[] args) {
Popper popper = new Popper();
Lights lights = new Lights();
Screen screen = new Screen();
Projector projector = new Projector();
Amp amp = new Amp();
Dvd dvd = new Dvd();
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(popper, lights, screen, projector, amp, dvd);
homeTheaterFacade.watchMovie();
}
}
定义外观模式
全部内容就是这样,现在又学会了一个模式,通过这个模式引导出了一个新的设计原则。
“最少知识”原则
最少知识(Least Knowledge) 原则告诉我们要减少对象之间的交互,只留下几个“密友”。这个原则通常是这么说的:
最少知识原则:之和你的密友谈话。
这是说,当你正在设计一个系统,不管是任何对象,你都要注意它所交互的类有哪些,并注意它和这些类是如何交互的。
这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人了解。
究竟要怎么才能避免这样呢?这个原则提供了一些方针,就任何对象而言,在该对象的方法内,我们只应该调用属于一下范围的方法:
- 该对象本身;
- 被当作方法的参数而传递进来的对象;
- 此方法所创建或实例化的任何对象;
- 对象的任何组件;
前三条是说,如果某对象是调用其他的方法的返回结果,不要调用该对象的方法;
最后一条是说,把“组件”想成是被实例变量所引用的任何对象,换句话说,把这想象成是Has-A的关系。
例如:
// 未使用最少知识原则
public float getTemp()
{
Thermometer thermometer = station.getThermometer();
return thermometer.getTemperature();
}
// 使用最少知识原则
public float getTemp()
{
return station.getTemperature();
}
上面的代码的第一个方法没有使用最少知识原则,首先从气象站取得了温度计对象,然后再从温度计对象取得了温度,getTemp()方法与两个对象在打交道。
第二个方法使用了最少知识原则,我们可以在气象站中加入一个getTemperature()方法获得温度,让getTemp()方法只与气象站一个对象打交道。
以上就是外观模式的内容。