设计模式之外观模式

外观模式

1.需求:设计一个家庭影院

组成部分: DVD遥控器,投影仪,自动屏幕,环绕立体声,爆米花机

过程: 开爆米花机 -> 放下屏幕 -> 开投影仪 -> 开音响 -> 开DVD,选择音乐 -> 调暗灯光 -> 播放电影 -> 观影结束,关闭所有设备

2.解决方案
  • 传统方案: 构建客户端,然后直接调用各个设备的一系列方法(下图中的ClientTest直接依赖于各个设备)
    在这里插入图片描述
  • 分析:通过ClientTest直接创建各个子系统的对象,直接调用子系统的相关方法,会造成调用过程的混乱,不利于维护操作
  • 解决思路: 使用外观模式
3.外观模式的基本介绍
  1. 外观模式(Facade Pattern),也称为“过程模式”,外观模式为子系统提供一个一致的界面,此界面定义了一系列子系统的引用。便于组合子系统的逻辑

  2. 自行定义规范(界面类),用来屏蔽内部子系统的细节,使得调用端只需要和这个(接口 or 类)发送调用,而无需关心子系统的内部细节

  3. 外观模式中的角色:

    1. 外观类(Facade) 为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当的子系统对象
    2. 调用者(Client) 外观接口的调用者
    3. 子系统(Sub System) :模块或者是子系统,处理Facade对象指派的任务(功能的实际提供者)
  4. 结构介绍:
    在这里插入图片描述

4.外观模式解决家庭影院问题

1.结构图
这里的HmeTheaterFacade是界面类,内部组合多个子系统。用来进行子系统逻辑的整理以及设计与调用者之间的交互逻辑。
在这里插入图片描述
2.代码演示

//子系统一览 Sub System
public class DVDPlayer {
    //使用单例模式(饿汉式)
    private static DVDPlayer instance = new DVDPlayer();
    public static DVDPlayer getInstance(){
        return instance;
    }

    //DVD的功能

    //开启
    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 pause");
    }
}
public class Popcorn {
    //使用单例模式(饿汉式)
    private static Popcorn instance = new Popcorn();
    public static Popcorn getInstance(){
        return instance;
    }

    //爆米花机的功能

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

}
//投影仪
public class Projector {
    private static Projector instance = new Projector();
    public static Projector getInstance(){
        return instance;
    }

    //投影仪功能
    //开启
    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");
    }
}
//屏幕
public class Screen {
    private static Screen instance = new Screen();

    public static Screen getInstance() {
        return instance;
    }




    public void up() {
        System.out.println(" Screen up ");
    }

    public void down() {
        System.out.println(" Screen down ");
    }

}
//立体声
public class Stereo {
    private static Stereo instance = new Stereo();

    public static Stereo getInstance() {
        return instance;
    }

    public void on() {
        System.out.println(" Stereo on ");
    }

    public void off() {
        System.out.println(" Screen off ");
    }

    public void up() {
        System.out.println(" Screen up.. ");
    }

    //...
}

//灯光
public class TheaterLight {
    private static TheaterLight instance = new TheaterLight();

    public static TheaterLight getInstance() {
        return instance;
    }

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





//界面类(Facade) 承上启下
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();
        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();
        dVDPlayer.off();
    }


}



```java
//Client 调用者
public class Client {
    //如果直接调用客户端 很麻烦
    //调用顶层类
    public static void main(String[] args) {
        HomeTheaterFacade facade = new HomeTheaterFacade();
        facade.ready();
        facade.play();
        facade.pause();
        facade.end();
    }
}

3.运行结果
在这里插入图片描述

注: 如果单纯地在Client中直接使用子系统的话,必然会导致Client内部调用多个子系统,逻辑复杂且紊乱,所以使用外观模式,在子系统之上加了一层“外观类”,进行子系统的整理。方便client调用,好像现在手机上的“一键安装功能”,或者点餐的时候直接点“套餐”;

关于外观模式的细节
  • 外观模式降低客户端和子系统的耦合性,便于维护和扩展
  • 外观模式对外屏蔽了子系统的细节,降低了客户端对子系统使用的复杂性
  • 当系统进行分层设计的时候,可以考虑使用外观模式
  • 当如果直接调用多个子系统进行复杂操作的时候,可以考虑使用外观模式
  • 外观模式的优缺点
    • 优点:
      • 简化调用流程,客户端不需要知道子系统的实现,提高了安全性,符合“迪米特原则”。
      • 提高灵活性,降低用户类和子系统类的耦合度,实现了松耦合。
      • 更好的划分访问层次。
    • 缺点:
      • 如果新增子系统,需要修改外观类,违背了“开闭原则”。

参考资料:
https://www.jianshu.com/p/f9d250ed59dc
图解java设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值