外观模式-Facade

外观模式通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。外观模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

一、类图

 外观模式包含如下几个角色:

  • 外观(Facade)角色 :为多个子系统对外提供一个共同的接口。
  • 子系统(SubSystem)角色 :实现系统的部分功能,客户可以通过外观角色访问它。

二、示例

搭建一个家庭影院系统,系统内包含设备:DVD播放器、投影机、自动屏幕、立体声音响、爆米花机。

定义这些媒体类:

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("弹出CD播放器!");
    }
    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("正在调暗灯光。。");
    }
 
}

外观模式类:俩方法,一个看电影-打开一系列设备,一个电影结束-关闭一系列设备

//定义外观模式家庭影院
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();
    }
}

客户端

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");
    }
 
}

通过上面的代码可以看出,每个类对象都要执行一些方法,如果直接new这些类创建对象去调方法会与这些类产生耦合,这时单独再写一个外观类,构造初始化时拿到这些类对象,在一个方法里去调这些类对象的方法,这样对客户来说只和一个类打交道,与子系统的一堆类解耦了。此类原则即为:最少知识原则。

客户端只和外观谈话,不和子设备,如DVD播放机、投影仪等谈话,降低了客户端和设备的耦合度。

 

 ……更多设计模式的内容,可以访问Refactoring.Guru
posted @ 2019-10-29 18:06  静水楼台/Java部落阁  阅读(185)  评论(0编辑  收藏  举报