java设计模式之外观模式

一、外观模式简介
我们已经知道适配器模式是如何将一个类的接口转换成另一个符合客户期望的接口的。现在我们要看一个改变接口的新模式,但是它改变接口的原因是为了简化接口。这个模式被巧妙地命名为外观模式,之所以这么称呼,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
使用场景:
1、JAVA 的三层开发模式。
2、为复杂的模块或子系统提供外界访问的模块。 
3、维护子系统相对独立。

二、实例演示
1、业务需求
假如我们需要在家里面看电影,那么必须先执行一些任务:
(1)打开爆米花机;
(2)开始爆米花;
(3)将灯光调暗;
(4)放下屏幕;
(5)打开投影机;
(6)将投影机的输入切换到DVD;
(7)将投影机设置在宽屏模式;
(8)打开功放;
(9)将功放的输入设置为DVD;
(10)将功放设置为环绕立体声;
(11)将功放音量调到中;
(12)打开DVD播放器;
(13)开始播放DVD。
我们将这些任务封装成类和方法的调用:

// 打开爆米花机,开始爆米花
popper.on();
popper.pop();
 
// 灯光调到10%的亮度
lights.dim(10);
 
// 把屏幕放下来
screen.down();
 
// 打开投影机,并将它设置在宽屏模式
projector.on();
projector.setInput(dvd);
projector.wideScreenMode();
 
// 打开功放,设置为DVD,调整成环绕立体声模式,音量调到5
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
 
// 打开DVD机,终于可以看电影了!
dvd.on();
dvd.play(movies);

但是这样操作有十分大的隐患,例如看完电影后,你还要把一切都关掉,怎么办?难道要反向地把这一切动作再进行一次?这显然是不好的。这里我们来使用外观模式来对这个业务进行包装。

2、外观模式实现
我们了创建一个名为HomeTheaterFacade的新类,它对外暴露出几个简单的方法,例如watchMovie()。这个外观类将家庭影院的诸多组件视为一个系统,通过调用这个子系统,来实现watchMovie()方法。现在,我们可以调用此家庭影院外观所提供的方法例如watchMovie(),而不必再调用这个子系统的方法。所以,想要看电影,我们只要调用一个方法(也就是watchMovie())就可以了。灯光、DVD播放器、投影机、功放、屏幕、爆米花,一口气全部搞定。
外观只是提供更直接的操作,并未将原来的子系统阻隔起来。如果需要子系统类的更高层功能,还是可以使用原来的子系统。
首先定义HomeTheaterFacade类:

public class HomeTheaterFacade {
    // 这是组合:我们会用到的子系统组件全部在这里
    Amplifier amp;
    Tuner tuner;
    DvdPlayer dvd;
    CdPlayer cd;
    Projector projector;
    TheaterLights lights;
    Screen screen;
    PopcornPopper popper;
 
    // 外观将子系统中每一个组件的引用都传入构造器中。
    // 然后外观把它们赋值给相应的实例变量
    public HomeTheaterFacade(Amplifier amp,
                             Tuner tuner,
                             DvdPlayer dvd,
                             CdPlayer cd,
                             Projector projector,
                             TheaterLights lights,
                             Screen screen,
                             PopcornPopper popper) {
        this.amp = amp;
        this.tuner = tuner;
        this.dvd = dvd;
        this.cd = cd;
        this.projector = projector;
        this.lights = lights;
        this.screen = screen;
        this.popper = popper;
    }
}


然后将子系统的组件整合成一个一个的统一的方法,具体就是watchMovie()和endMovie()方法。

public void watchMovie(String movie){
    // watchMovie()将我们之前手动进行的每项任务依次处理。
    // 请注意,每项任务都是委托子系统中相应的组件处理的。
    System.out.println("Get ready to watch a movie");
    popper.on();
    popper.pop();
    lights.dim(10);
    screen.down();
    projector.on();
    projector.wideScreenMode();
    amp.on();
    amp.setDvd(dvd);
    amp.setSurroundSound();
    amp.setVolume(5);
    dvd.on();
    dvd.play(movie);
}
 
public void endMovie(){
    // endMovie()负责关闭一切。每项任务也是委托子系统中合适的组件处理的。
    System.out.println("Shutting movie theater down");
    popper.off();
    lights.on();
    screen.up();
    projector.off();
    amp.off();
    dvd.stop();
    dvd.eject();
    dvd.off();
}


最后我们可以调用方法来看电影和关闭影院了。

//之前已经对各个组件进行了初始化
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, lights, screen, popper);
homeTheaterFacade.watchMovie("The Lord of Rings");//观看电影
homeTheaterFacade.endMovie();//关闭影院


三、总结

想要使用外观模式,我们创建了一个接口简化而统一的类,用来包装子系统中一个或多个复杂的类。外观模式相当直接,很容易理解,这方面和许多其他的模式不太一样。但这并不会降低它的威力:外观模式允许我们让客户和子系统之间避免紧耦合。外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。



原文地址:https://www.cnblogs.com/kangsir/p/6653222.html