• 设计模式之外观模式案例详解


    基本概念

    外观模式(Facade),也叫“过程模式”。外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

    外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用, 而无需关心这个子系统的内部细节。

    外观模式可以理解为转换一群接口,客户只要调用一个接口,而不用调用多个接口才能达到目的。比如,在pc上安装软件的时候经常有一键安装选项(省去选择安装目录、安装的组件等等),还有就是手机的重启功能(把关机和启动合为一个操作)。

    外观模式就是解决多个复杂接口带来的使用困难,起到简化用户操作的作用。

    外观模式原理类图

    • 外观类(Facade):为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象。
    • 调用者(CLient):外观接口的调用者。
    • 子系统的集合:指模块或者子系统,处理Facade对象指派的任务,它是功能的实际提供者。

    传统方式

    案例

    影院管理项目:组建一个家庭影院:DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,其过程为使用遥控器统筹各设备开关。

    思路分析

    问题分析

    在ClientTest的main方法中,创建各个子系统的对象,并直接区调用子系统(对象)相关方法,会造成调用过程混乱,没有清晰的过程。

    不利于在ClientTest中,去维护对子系统的操作。

    解决思路:定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比如在高层接口提供三个方法ready,play,end),用来访问子系统中的一群接口。

    也就是说,就是通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节(外观模式)。

    外观模式

    思路分析

    代码实现

     1public class DVDPlayer {
    2
    3    //使用单例模式,使用饿汉式
    4    private static DVDPlayer instance=new DVDPlayer();
    5
    6    private DVDPlayer(){//构造器私有化
    7    }
    8
    9    public static DVDPlayer getInstance(){
    10        return instance;
    11    }
    12
    13    public void on(){
    14        System.out.println("DVD打开");
    15    }
    16
    17    public void off(){
    18        System.out.println("DVD关闭");
    19    }
    20
    21    public void play(){
    22        System.out.println("DVD正在播放");
    23    }
    24}

     1public class Popcorn {
    2
    3    private static Popcorn instance=new Popcorn();
    4
    5    private Popcorn(){
    6    }
    7
    8    public static Popcorn getInstance(){
    9        return instance;
    10    }
    11
    12    public void on(){
    13        System.out.println("爆米花机打开");
    14    }
    15
    16    public void off(){
    17        System.out.println("爆米花机关闭");
    18    }
    19
    20    public void pop(){
    21        System.out.println("爆米花机正在制作爆米花");
    22    }
    23}

     1public class Projector {
    2
    3    private static Projector instance=new Projector();
    4
    5    private Projector(){
    6    }
    7
    8    public static Projector getInstance(){
    9        return instance;
    10    }
    11
    12    public void on(){
    13        System.out.println("投影仪打开");
    14    }
    15
    16    public void off(){
    17        System.out.println("投影仪关闭");
    18    }
    19
    20    public void focus(){
    21        System.out.println("投影仪正在聚焦");
    22    }
    23}

     1public class Screen {
    2
    3    private static Screen instance=new Screen();
    4
    5    private Screen(){
    6    }
    7
    8    public static Screen getInstance(){
    9        return instance;
    10    }
    11
    12    public void up(){
    13        System.out.println("屏幕上升");
    14    }
    15
    16    public void down(){
    17        System.out.println("屏幕下降");
    18    }
    19}

     1public class Stereo {
    2
    3    private static Stereo instance=new Stereo();
    4
    5    private Stereo(){
    6    }
    7
    8    public static Stereo getInstance(){
    9        return instance;
    10    }
    11
    12    public void on(){
    13        System.out.println("立体声打开");
    14    }
    15
    16    public void off(){
    17        System.out.println("立体声关闭");
    18    }
    19}

     1public class TheaterLight {
    2
    3    private static TheaterLight instance=new TheaterLight();
    4
    5    private TheaterLight(){
    6    }
    7
    8    public static TheaterLight getInstance(){
    9        return instance;
    10    }
    11
    12    public void on(){
    13        System.out.println("灯光打开");
    14    }
    15
    16    public void off(){
    17        System.out.println("灯光关闭");
    18    }
    19
    20}

     1public class HomeTheaterFacade {
    2
    3    //定义各个子系统对象
    4    private TheaterLight theaterLight;
    5    private Popcorn popcorn;
    6    private Stereo stereo;
    7    private Projector projector;
    8    private Screen screen;
    9    private DVDPlayer dvdPlayer;
    10
    11    public HomeTheaterFacade() {
    12        this.theaterLight = TheaterLight.getInstance();
    13        this.popcorn = Popcorn.getInstance();
    14        this.stereo = Stereo.getInstance();
    15        this.projector = Projector.getInstance();
    16        this.screen = Screen.getInstance();
    17        this.dvdPlayer = DVDPlayer.getInstance();
    18    }
    19
    20    //操作分为四步
    21    public void ready(){
    22        theaterLight.on();
    23        projector.on();
    24        popcorn.on();
    25        stereo.on();
    26        screen.up();
    27        dvdPlayer.on();
    28    }
    29
    30    public void play(){
    31        dvdPlayer.play();
    32    }
    33
    34    public void end(){
    35        theaterLight.off();
    36        projector.off();
    37        popcorn.off();
    38        stereo.off();
    39        screen.down();
    40        dvdPlayer.off();
    41    }
    42}

    1public class Client {
    2
    3    public static void main(String[] args) {
    4        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
    5        homeTheaterFacade.ready();
    6        homeTheaterFacade.play();
    7        homeTheaterFacade.end();
    8    }
    9}

    注意事项

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

    外观模式对客户端与子系统的耦合关系—解耦,让子系统内部的模块更易维护和扩展。

    通过合理的使用外观模式,可以帮我们更好的划分访问的层次。

    当系统需要进行分层设计时,可以考虑使用Facade模式。

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

    不能过多的或者不合理的使用外观模式,要让系统有层次,利于维护为目的。

  • 相关阅读:
    Qt 学习 之 二进制文件读写
    QT学习 之 文本文件读写
    Qt学习 之 文件
    QT学习 之 三维饼图绘制
    Haskell 笔记(四)函数系统
    QT学习 之 事件与事件过滤器(分为五个层次)
    Qt学习 之 数据库(支持10种数据库)
    Qt5制作鼠标悬停显示Hint的ToolTip
    【码云周刊第 32 期】程序员眼中的 Vue 与 Angular !
    Qt学习 之 多线程程序设计(QT通过三种形式提供了对线程的支持)
  • 原文地址:https://www.cnblogs.com/fairboyllil/p/13423135.html
Copyright © 2020-2023  润新知