设计模式之外观模式

放弃该放弃的是无奈,放弃不该放弃的是无能,不放弃该放弃的是无知,不放弃不该放弃的是执着。

愿自己能在自己所热爱的道路上越走越远。


设计模式之外观模式

我们先来看看外观模式的核心定义: 下面是我自己的理解, 如果觉的由不符合的,请留言指出.

  1. 外观设计模式的顶层接口内部聚合了其子系统的顶层接口,而外观设计模式的核心是通过该顶层及接口来显示控制其子系统的调用过程.
  2. 外观设计模式对其聚合的子系统的实现细节进行了屏蔽,让子系统内部更容易维护和扩展.
外观设计模式子系统代码的实现

在这里我们举生活中常见的例子来用外观模式进行实现:
我们在家里看电影的时候,如果要吃爆米花那么就应该先 打开爆米花机,然后在进行打造爆米花, 然后是对屏幕的一些操作,接着有了屏幕那么就需要对投影仪做一些操作,那么之后就需要对立体声音做一些操作,然然后就是打开dvd以及关灯. 上面说的一些过程, 如果说在我们不使用改观模式的话, 那么其在客户端使用的时候及其复杂,并且如果某个子系统进行了修改或者增加新的模式,那么客户端也就要相应的进行修改,其违背了OCP设计原则. 那么下面将展示使用了外观设计模式的
虽然其子系统是很简单的代码,但是由于是在博客里面进行对设计模式的一个演练,所以说每个子系统仅仅用了一个简单的实例来展示.

Dvd播放机子系统

/**
 * 设计模式外观模式之内部组件之一: Dvd。
 * <p>
 * 该模式中使用了到了单例模式.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:10
 */
public class DvdPlay {

    /**
     * DCL单例模式下该instance必须被volatile修饰。
     */
    private static volatile DvdPlay instance = null;

    /**
     * 构造函数私有化.
     */
    private DvdPlay() {
    }

    /**
     * 通过暴露该一个外部访问该类的一个接口. DCL.
     * <p>
     * 这里说明下为什么DCL单例模式为什么需要添加volatile关键字: 如果不添加volatile关键字那么就会出现以下一种情况:
     * 假如说第一个线程获取到了DvdPlay.class对象锁,并且还没有将instance进行赋值,假如说当一个线程赋值之后就退出同步块之后,第二个线程立马
     * 就进来,但此时线程1对instance赋的值还没有从线程本地内存中写会到主内存,而这个时候线程而已经进入同步块了并且也进行了判断,这个时候instance
     * 实例将会进行多次赋值,那么DCL单例也就没有起到单例的效果.
     *
     * @return 返回一个DvdPlay的实例.
     */
    public static DvdPlay getInstance() {

        if (instance == null) {

            synchronized (DvdPlay.class) {

                if (instance == null) {

                    instance = new DvdPlay();

                }

            }

        }

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

    public void pause() {

        System.out.println(" dvd pause");
    }

}

爆米花子系统

/**
 * 看电影的时候吃的爆米花.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:38
 */
public class 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");
    }
    
}

投影仪子系统

/**
 * 模拟投影仪.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:40
 */
public class Projector {

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

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

    public void focus(){
        System.out.println(" projector focus");
    }
    
}

屏幕子系统

/**
 * 模拟屏幕.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:40
 */
public class Screen {

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

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

立体声子系统

/**
 * 模拟立体声.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:40
 */
public class 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");
    }
    
}

灯光子系统

/**
 * 模拟灯光.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:41
 */
public class TheaterLight {

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

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

    public void dim (){
        System.out.println("  light dim ..");
    }

    public void bright(){
        System.out.println(" light bright");
    }
    
}

最重要的外观模式的顶层设计接口:HomeFacade接口

/**
 * 外观模式的顶层接口.
 * <p>
 * 下面说一下外观设计模式的注意细节:
 * 1. 外观设计模式在形式上是通过多个组件的聚合来组成外观模式的顶层接口,然后在外观设计模式进行组装调用.
 * 2. 外观模式降低了客户端与子系统的耦合,让子系统内部更容易维护和扩展.
 * 3. 外观模式屏蔽了子系统的实现的细节,因此外观模式降低了客户端(使用者)对子系统使用的复杂性.
 * 3. 当系统需要分层设计的时候,可以使用外观模式,而外观模式的顶层接口在分层意思上就像是一层.
 * 4. 如果使用合理,那么就可以帮助我们更好的对系统进行分层设计,如果使用的不合理,那么将会造成,额外的负担.
 *
 * @author ZhenXinMa
 * @date 2020/9/4 22:41
 */
public class HomeFacade {

    /*
     * --------------------------------------------------------
     * 外观模式是将所有有关的类都聚合到Facade类中,然后统一进行调控.
     * --------------------------------------------------------
     * */

    private DvdPlay dvdPlay;

    private Popcorn popcorn;

    private Projector projector;

    private Screen screen;

    private Stereo stereo;

    private TheaterLight theaterLight;

    /**
     * 通过外观模式的主类,来将其聚合的所有相关的类都进行实例化.
     */
    public HomeFacade() {

        this.dvdPlay = DvdPlay.getInstance();
        this.popcorn = new Popcorn();
        this.projector = new Projector();
        this.screen = new Screen();
        this.theaterLight = new TheaterLight();
        this.stereo = new Stereo();
    }

    /**
     * 观看电影前的准备.
     */
    public void ready() {

        // 准备爆米花.
        this.popcorn.on();
        this.popcorn.pop();
        // 降低屏幕来观看电影.
        this.screen.down();
        // 打开投影仪.
        this.projector.on();
        // 模拟立体声.
        this.stereo.on();
        this.dvdPlay.on();
        // 关灯.
        this.theaterLight.dim();

    }

    /**
     * 在外观设计模式的顶层接口中,通过调用内部聚合的组件的各个方法组成play行为.
     */
    public void play() {

        this.dvdPlay.play();

    }

    public void pause() {

        dvdPlay.pause();

    }

    /**
     * 当电影看完之后,通过外观模式的顶层接口内部组装的各个子系统的顶层接口,进行具体的组装来实现结束操作.
     */
    public void end() {

        popcorn.off();
        screen.up();
        projector.off();
        stereo.off();
        dvdPlay.off();
        theaterLight.bright();

    }
    
}
外观设计模式使用注意事项:
  1. 当系统需要分层设计的时候可以使用外观设计模式,外观设计模式的顶层接口就是一个层面,其负责调控其子系统的调用执行顺序.
  2. 如果外观设计模式使用的合理,那么就可以很好地帮助我们对我们的系统进行分层设计, 如果使用的不合理,那么就会对整个系统造成额外的负担.
  3. 外观设计模式屏蔽了子系统实现的复杂性,降低了客户端与子系统的耦合,让子系统内部更容易扩展和维护.

外观设计模式在上面代码注释中也已经给出了详细的解释, 但是说如果想将外观模式做的更通用些. 那么可以为所有子系统抽象出他们各自的顶层接口,这样在外观模式的顶层接口中更是符合OCP原则. 在这篇文章中虽然没有给所以子系统设计一个顶层接口为了方便以后进行维护,那么在以后复习的时候可以为每一个子系统抽象出一个接口 来让外观顶层接口进行维护.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值