外观模式:提供了一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。
外观模式实现了最少知识原则(Least Knowledge principle),这个原则希望不要让太多的类耦合在一起,对用户来说只和一个外观类打交道了,达到客户和一群子系统的解耦。
话不多说、上实例:
老外要实现以家庭影院,他要看电影的时候要依次做这些事:
1.打开爆米花机
2.开始蹦爆米花
3.将灯光调暗
4.放下屏幕
5.打开投影仪
6.将投影仪设置为宽屏模式
7.打开功放
8.将功放的输入设置为DVD
9.将功放设置为环绕立体声、
10.打开DVD播放器
11.开始播放DVD
他不想走到每个机器面前按下按钮,就是不想和每个类打交道,让我们给设置一个按钮,按一下即执行全部动作
上图
1.先来定义这些多媒体类
class Amplifier{
public void on(){
System.out.println("欢迎使用功放类。。");
}
public void off(){
System.out.println("已经关闭功放。。");
}
public void setCD(){
System.out.println("正在安放CD。。。");
}
public void setDVD(){
System.out.println("正在安放DVD、。。");
}
public void setStereoSound(){
System.out.println("设置立体声。。");
}
public void setSurroundSound(){
System.out.println("设置环绕立体声。。");
}
public void setTime(){
System.out.println("正在设置时间。。");
}
public void setVolume(){
System.out.println("正在设置音量。。");
}
}
//定义Tuner类
class Tuner{
public void on(){
System.out.println("正在 打开调谐器。。");
}
public void off(){
System.out.println("正在关闭调谐器。。");
}
public void setAM(){
System.out.println("正在设置am。。");
}
public void setFM(){
System.out.println("正在设置频道。。");
}
public void setFrequency(){
System.out.println("正咋设置频道。。");
}
}
//定义DVD播放器类
class DVDPlayer{
public void on(){
System.out.println("正在打开DVD。。");
}
public void off(){
System.out.println("正在关闭DVD。。");
}
public void pause(){
System.out.println("已经暂停DVD播放。。");
}
public void play(){
System.out.println("正在播放DVD。。");
}
public void setTwoChannelAudio(){
System.out.println("正在设置双频道。。");
}
public void setSurroundAudio(){
System.out.println("正在设置环绕立体声。。");
}
}
//定义CD播放器
class CDPlayer{
public void on(){
System.out.println("正在打开CD");
}
public void off(){
System.out.println("正在关闭CD");
}
public void eject(){
System.out.println("eject 啥意思。。。");
}
public void pause(){
}
public void play(){
}
public String toString(){
return "hello panda";
}
}
//定义投影仪
class Projector{
public void on(){
System.out.println("正在打开投影仪。。");
}
public void off(){
System.out.println("正在关闭投影仪。。");
}
public void setTVMode(){
System.out.println("正在设置tv模式。。");
}
public void setWideScreenMode(){
System.out.println("正在设置宽屏模式。。");
}
}
//定义屏幕
class Screen{
public void up(){
System.out.println("正在生起屏幕。。");
}
public void down(){
System.out.println("正在放下屏幕。。");
}
}
//定义爆米花机
class PopcornPopper{
public void on(){
System.out.println("正在打开爆米花机。。");
}
public void off(){
System.out.println("正在关闭爆米花机。。");
}
public void pop(){
System.out.println("正在蹦爆米花。。");
}
}
//定义影院灯光
class TheaterLights{
public void on(){
System.out.println("正在打开灯光。。");
}
public void off(){
System.out.println("正在关闭灯光。。");
}
public void dim(){
System.out.println("正在调暗灯光。。");
}
}
2.多媒体的具体类准备好就可以定义外观模式类了俩方法,一个看电影-打开一系列设备,一个电影结束-关闭一系列设备
//定义外观模式家庭影院
class HomeTheaterFacade{
Amplifier amp;
Tuner tuner ;
DVDPlayer dvd;
CDPlayer cd;
Projector project;
TheaterLights light;
Screen screen;
PopcornPopper pop;
//构造的时候拿到这些对象
public HomeTheaterFacade(Amplifier amp,Tuner tuner,DVDPlayer dvd,
CDPlayer cd ,Projector project,TheaterLights light,Screen screen
,PopcornPopper pop){
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.project = project;
this.light = light;
this.screen = screen;
this.pop = pop;
}
//看电影 放一个方法里来执行一系列动作
public void watchMovie(String movie){
System.out.println("get ready to watch a movie..");
pop.on();//首先打开爆米花机
pop.pop();//然后蹦爆米花
light.dim();//把灯光调暗
screen.down();//投影仪放下来
project.on();
project.setWideScreenMode();
amp.on();
amp.setDVD();
amp.setSurroundSound();
amp.setVolume();
dvd.on();
dvd.play();
}
//电影结束
public void endMovie(String movie){
System.out.println("shutting movie theater down..");
pop.off();
light.on();
screen.up();
project.off();
amp.off();
dvd.off();
}
}
3.现在来简单测试一下吧
public class FacadePattern {
public static void main(String args[]){
Amplifier amp = new Amplifier();
Tuner tuner = new Tuner() ;
DVDPlayer dvd = new DVDPlayer();
CDPlayer cd = new CDPlayer();
Projector project = new Projector();;
TheaterLights light = new TheaterLights();
Screen screen = new Screen();
PopcornPopper pop = new PopcornPopper();
HomeTheaterFacade facade = new HomeTheaterFacade(amp,tuner,dvd,cd,project,light,screen,pop);
facade.watchMovie("movie");
facade.endMovie("movie");
}
}
4.运行结果
get ready to watch a movie..
正在打开爆米花机。。
正在蹦爆米花。。
正在调暗灯光。。
正在放下屏幕。。
正在打开投影仪。。
正在设置宽屏模式。。
欢迎使用功放类。。
正在安放DVD、。。
设置环绕立体声。。
正在设置音量。。
正在打开DVD。。
正在播放DVD。。
shutting movie theater down..
正在关闭爆米花机。。
正在打开灯光。。
正在生起屏幕。。
正在关闭投影仪。。
已经关闭功放。。
正在关闭DVD。。
*我的理解是这样的:
就是由一堆类,每个类对象都要执行一些方法,如果直接new这些类创建对象去调方法会与这些类产生耦合,这时单独再写一个外观类,构造初始化时拿到这些类对象,在一个方法里去调这些类对象的方法,这样对客户来说只和一个类打交道,与子系统的一堆类解耦了。*
适配器模式 PK 外观模式
1.当需要使用一个现有的类,而其接口并不符合你的需要时,就使用适配器。
2.当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观。
1.适配器改变接口以符合客户的希望
2.外观将一个客户从复杂的子系统中解耦。
1.实现一个适配器可能需要一番功夫,也可能不费工夫,视目标接口的大小与复杂度而定。
2.实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。
1.适配器模式有两种形式,对象适配器和类适配器。类适配器需要用到多重继承。
2.你可以为一个子系统实现一个以上的外观。
1.适配器将一个对象包装起来以改变其接口;装饰器将一个对象包装起来以增加新的行为和责任,而外观将一群对象包装起来以简化其接口。