门面模式就是这么简单

上篇文章咱们学习了适配器模式,咱们知道它是将一个接口转换成另外一个符合用户指望的接口,它的主要目的是为了兼容,将一个不兼容接口的对象包装起来,变成兼容的对象。java

这篇文章咱们来学习一下门面模式,它又称为外观模式,与适配器模式看起来很相似,但它主要是为了简化接口,下面就来具体看一下。设计模式

门面模式

不知道你们平时是否有这样的经历。天天开启电脑后,要打开各类软件、IDE、工具,就须要一个一个地点击桌面图标;到了晚上又要一个个地关闭,感受很是麻烦。框架

这里举几个例子,首先是 Intellj IDEA:ide

public class IDEA {

    public void on() {
        System.out.println("打开 IDEA");
    }
    public void off() {
        System.out.println("关闭 IDEA");
    }
}
复制代码

而后是 Google:工具

public class Google {

    private List<Tab> tabs = new ArrayList<>();

    public void on() {
        System.out.println("打开 google");
    }
    public void off() {
        System.out.println("关闭 google");
    }
    public void onTabs() {
        System.out.println("打开 ProcessOn、七牛云等 Tab");
    }
}
复制代码

还有有道云笔记:学习

public class YouDaoNote {
    public void on() {
        System.out.println("打开 YouDaoNote");
    }
    public void off() {
        System.out.println("关闭 YouDaoNote");
    }
}
复制代码

可能还会有 Weixin:ui

public class WeiXin {

    public void on() {
        System.out.println("打开 WeiXin");
    }
    public void off() {
        System.out.println("关闭 WeiXin");
    }
}
复制代码

另外,可能还会有 Shell、CloudMusic 等。咱们开启软件时,能够以下写:this

public class Client {

    public static void main(String[] args) {
        IDEA idea = new IDEA();
        Google google = new Google();
        YouDaoNote youDaoNote = new YouDaoNote();
        WeiXin weiXin = new WeiXin();

        idea.on();
        google.on();
        google.onTabs();
        youDaoNote.on();
        weiXin.on();
    }
}
复制代码

在关闭时,又将这些步骤反过来执行一遍,那也太麻烦了。其实,咱们能够写一个 bat 脚本,每次只须要执行这个脚本,就能够开启多个软件。google

这个脚本就是所谓的门面,如今咱们来建立一个门面,它将不一样的软件组合成一个统一的接口:idea

public class DevelopmentEnvironment {

    private IDEA idea;
    private Google google;
    private YouDaoNote youDaoNote;
    private WeiXin weiXin;
    public DevelopmentEnvironment(IDEA idea, Google google, YouDaoNote youDaoNote, WeiXin weiXin) {
        this.idea = idea;
        this.google = google;
        this.youDaoNote = youDaoNote;
        this.weiXin = weiXin;
    }

    public void buildEnvironment() {
        idea.on();
        google.on();
        google.onTabs();
        youDaoNote.on();
        weiXin.on();
    }
    public void shutEnvironment() {
        idea.off();
        google.off();
        youDaoNote.off();
        weiXin.off();
    }
}
复制代码

它对外只暴露了几个方法,因而咱们创建开发环境能够这样写:

public class Client {

    public static void main(String[] args) {
        IDEA idea = new IDEA();
        Google google = new Google();
        YouDaoNote youDaoNote = new YouDaoNote();
        WeiXin weiXin = new WeiXin();

        DevelopmentEnvironment environment = new DevelopmentEnvironment(idea, google, youDaoNote, weiXin);
        environment.buildEnvironment();
    }
}
复制代码

上述模式就是门面模式,它提供了一个统一的接口,来访问子系统的多个接口,使得子系统更容易使用。

它的 UML 图以下:

下面来总结一下门面模式的优势:

  • 经过统一的接口,来访问子系统的多个接口。如此就无需了解子系统的实现,简化了调用的过程。
  • 减小了客户和子系统之间的系统依赖,耦合度更低。
  • 门面模式很好得符合了最少知道原则。

缺点:

  • 若是增长子系统,或者扩展子系统的行为,可能会引入风险;
  • 系统设计不当时,增长子系统可能须要修改门面类,这违背了开闭原则。

最少知道原则

其实门面模式很好地符合了最少知道原则,它指的是尽可能减小对象之间的交互。在设计中,咱们应该减小类之间的耦合度,以避免修改系统中一部分,而影响到其余部分。

为知足该原则,咱们应该只调用属于如下范围的方法:

  1. 该对象自己;
  2. 被看成方法的参数而传递进来的对象;
  3. 此方法所建立或实例化的任何对象;
  4. 对象的任何组件;

例以下面的例子就符合最少知识原则:

public class Car {
    Engine engine; // 对象的组件
    
    public Car() {}
    
    // key 为做为方法参数传递进来的对象
    public void start(Key key) {
        Door door = new Door(); // 该方法中建立的对象
        
        boolean authorized = key.turn(); // 调用做为方法参数传递进来的对象的方法,2
        if(authorized) {
            engine.start(); // 调用组件的方法 // 4
            updateDashboardDisplay(); // 调用对象自己的方法 // 1
            door.lock(); // 调用该方法中建立的对象的方法 // 2
        }
    }
    
    // 对象自己的方法
    public void updateDasnboardDisplay() {}
}
复制代码

门面模式的具体实践

在实际项目中,咱们都会记录应用的执行日志,经常使用的日志框架有许多,而不一样的中间件会集成不一样的日志框架,当集成这些中间件时,咱们的系统不得不维护去多种日志框架。

因而,咱们能够引入一个中间层,由这个中间层来决定使用哪个具体的日志实现。这个中间层就是日志门面,咱们在打印日志时,只须要调用日志门面的 API,而不须要关心日志具体的实现。

日志门面和日志实现主要有:

  • 日志门面(日志的抽象层):slf4j、jcl(commons-logging);
  • 日志实现:jul(java.util.logging)、logback、log4j、log4j2;

具体它们的原理,这里就不说了。

在实际使用时,例如 SpringBoot 中默认使用 Slfj + Logback 组合来打印日志。

参考资料

  • 《Head First 设计模式》
相关文章
相关标签/搜索