zoukankan      html  css  js  c++  java
  • 设计模式之外观模式

     外观模式介绍:外观模式(Facade),也叫"过程模式", 外观模式为子系统中的一组接口提供一个一致的界面,此模式定了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式通过定义一个一致的接口,用以屏蔽内部子雄他那个的细节,使得调用端只需要跟这个接口发生调用,而不需关心这个子系统的内部细节。

    外观模式的原理类图如下:

     

     有一个外观类,里面聚合了各个子系统,然后Client客户端依赖使用这个外观类。

    外观类(Facade):为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求。从而将调用端的请求代理给子系统对象。

    调用者类(Client) :外观接口调用者

    子系统的集合:指模块或者子系统,处理Facade对象指派的一个任务,他是功能的实际提供者。

    创建一个家庭影院的项目,DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求用java完成家庭影院的功能。

    使用过程:

    1、直接用遥控器,统筹各种设备开关

    2、开爆米花机

    3、放下屏幕

    4、开投影仪

    5、升音响

    6、开DVD, 选dvd

    7、去拿爆米花

    8、调暗灯光

    9、播放

    10、观影结束关闭各种设备

    如果用传统方式解决的话,大家容易想到的是,创建出一系列的遥控器类,每个遥控器类控制不同的功能,但是这样势必会造成遥控器类非常多。如下

    那么以上解决方案的主要问题如下:

    1、子系统对象非常多,操作步骤多,会造成调用过程混乱,没有清晰的过程。

    2、不利于在ClientTest中去维护子系统的操作。如果各个子系统需要修改,造成ClientTest也需要跟着修改。

    解决思路:

    定义一个高层接口,给子系统的一组接口提供一个一致的界面(比如在高层接口提供ready,play,pause,end),用来访问子系统中的一群接口。也就是定义一个一致的接口(界面类),用以屏蔽子系统的细节,使得调用端只跟整个接口发生调用,而无需关心这个子系统的内部细节。=》引入外观模式。

    代码实现:

    TheaterLight.java

    public class TheaterLight {
        private static TheaterLight theaterLight = new TheaterLight();
        public static TheaterLight getInstance(){
            return theaterLight;
        }
        public void on(){
            System.out.println("theaterLight on");
        }
        public void off(){
            System.out.println("theaterLight off");
        }
        public void dim(){
            System.out.println("theaterLight dim");
        }
        public void bright(){
            System.out.println("theaterLight bright");
        }
    }

    Stereo.java

    public class Stereo {
        private static Stereo stereo = new Stereo();
        public static Stereo getInstance(){
            return stereo;
        }
        public void on(){
            System.out.println("Stereo on");
        }
        public void off(){
            System.out.println("Stereo off");
        }
        public void up(){
            System.out.println("Stereo up");
        }
        public void down(){
            System.out.println("Stereo down");
        }
    }

    Screen.java

    public class Screen {
        private static Screen screen = new Screen();
        public static Screen getInstance(){
            return screen;
        }
        public void up(){
            System.out.println("Screen up");
        }
        public void down(){
            System.out.println("Screen down");
        }
    }

    Projector.java

    public class Projector {
        private static Projector projector = new Projector();
        public static Projector getInstance(){
            return projector;
        }
        public void on(){
            System.out.println("Projector on");
        }
        public void off(){
            System.out.println("Projector off");
        }
        public void focus(){
            System.out.println("Projector is focusing");
        }
    }

    Popcorn.java

    public class Popcorn {
        private static Popcorn popcorn = new Popcorn();
        public static Popcorn getInstance(){
            return popcorn;
        }
        public void on(){
            System.out.println("Popcorn on");
        }
        public void off(){
            System.out.println("Popcorn off");
        }
        public void pop(){
            System.out.println("Popcorn is poping");
        }
    }

    DVDPlayer.java

    public class DVDPlayer {
        private static DVDPlayer instance = new DVDPlayer();
        public static DVDPlayer getInstance(){
            return instance;
        }
        public void on(){
            System.out.println("dvd on");
        }
        public void off(){
            System.out.println("dvd off");
        }
        public void play(){
            System.out.println("dvd is playing");
        }
        public void pause(){
            System.out.println("dvd is pausing");
        }
    }

    HomeTheaterFacade.java

    public class HomeTheaterFacade {
        //定义各个子系统的对象
        private TheaterLight theaterLight;
        private Popcorn popcorn;
        private Stereo stereo;
        private Projector projector;
        private Screen screen;
        private DVDPlayer dvdPlayer;
    
        //构造器
        public HomeTheaterFacade() {
            super();
            this.theaterLight = TheaterLight.getInstance();
            this.popcorn = Popcorn.getInstance();
            this.stereo = Stereo.getInstance();
            this.projector = Projector.getInstance();
            this.screen = Screen.getInstance();
            this.dvdPlayer = DVDPlayer.getInstance();
        }
    
        //操作分为4个步骤
        public void ready(){
            //爆米花机打开
            popcorn.on();
            //爆米花机工作
            popcorn.pop();
            //屏幕放下
            screen.down();
            //投影仪打开
            projector.on();
            //立体声打开
            stereo.on();
            //dvd打开
            dvdPlayer.on();
            //灯光调暗
            theaterLight.dim();
        }
    
        //开始播放
        public void play(){
            dvdPlayer.play();
        }
        //停止
        public void pause(){
            dvdPlayer.pause();
        }
        //结束
        public void end(){
            //爆米花机关闭
            popcorn.off();
            //灯光打开
            theaterLight.bright();
            //屏幕升起来
            screen.up();
            //关闭投影仪
            projector.off();;
            //立体声关闭
            stereo.off();
            //关闭dvd
            dvdPlayer.off();
        }
    }

    Client.java

    public class Client {
        public static void main(String[] args) {
            HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
            homeTheaterFacade.ready();
            homeTheaterFacade.play();
            homeTheaterFacade.pause();
            homeTheaterFacade.end();
        }
    }

    外观模式的注意事项和细节

    1)外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性。

    2)外观模式对客户端与子系统的耦合关系进行解耦,使子系统内部的模块更易于维护和扩展。

    3)通过外观模式,可以帮助我们更好的划分访问的层次。

    4)当系统需要分层设计时可以考虑Facade模式。

    5)在维护一个遗留的大系统时,可能这个系统已经十分的难以维护和拓展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade类交互,提高复用性。

    6)不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好,要以让系统有层次,利于维护为目的。

  • 相关阅读:
    智能指针shared_ptr新特性shared_from_this及weak_ptr
    reactor模型框架图和流程图 libevent
    memset struct含有string的崩溃
    对于socket发送数据时是否要加锁及write read的阻塞非阻塞
    记录智能指针使用shared_ptr使用错误
    本地缓存和redis
    关于数据结构跳表的一些介绍
    linux 下source、sh、bash、./执行脚本的区别
    socket端口复用问题一二
    MD5算法
  • 原文地址:https://www.cnblogs.com/chenmz1995/p/12486691.html
Copyright © 2011-2022 走看看