设计模式 | 外观模式/门面模式(facade)

定义:

为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

结构:(书中图,侵删)

一个简洁易用的外观类
一个复杂的子系统
 

实例:

书中提到了理财的例子,找理财经理就不用自己研究各种股票债券什么了;致使我一度脑子里只想到了房屋中介,感觉跳不出这个框架了。
最后,终于让我想到了别的例子:有困难找警察。
我们只需要记住“110”这个电话号码就完事了,具体问题怎么处理就辛苦警察同志了。
接下来代码实现:
外观类:打110
package designpattern.facade;

public class HandleTrouble {
    public void call110(String trouble) {
        System.out.println(trouble);
        // 模拟接警员处理来电
        if (trouble.indexOf("抢劫") > 0 || trouble.indexOf("杀人") > 0) {
            CriminalPolice criminalPolice = new CriminalPolice();
            criminalPolice.handleIt();
        } else if (trouble.indexOf("追尾") > 0 || trouble.indexOf("撞车") > 0) {
            TrafficPolice trafficPolice = new TrafficPolice();
            trafficPolice.handleIt();
        } else if (trouble.indexOf("起火") > 0 || trouble.indexOf("烧起来") > 0) {
            System.out.println("转接火警...");
            FirePolice firePolice = new FirePolice();
            firePolice.handleIt();
        } else {
            PeoplePolice peoplePolice = new PeoplePolice();
            peoplePolice.handleIt();
        }
    }
}
复杂的警察子系统:各个部门
package designpattern.facade;

public class CriminalPolice {
    public void handleIt() {
        System.out.println("刑警出动...");
    }
}
package designpattern.facade;

public class TrafficPolice {
    public void handleIt() {
        System.out.println("交警出动...");
    }
}
package designpattern.facade;

public class FirePolice {
    public void handleIt() {
        System.out.println("火警出动...");
    }
}
package designpattern.facade;

public class PeoplePolice {
    public void handleIt() {
        System.out.println("民警出动...");
    }
}
客户端:
package designpattern.facade;

public class Client {
    public static void main(String[] args) {
        HandleTrouble handleTrouble = new HandleTrouble();
        handleTrouble.call110("救命啊,杀人啦,快来人啊~~~~~");
        System.out.println("-------------------");
        handleTrouble.call110("XX大楼起火了");
        System.out.println("-------------------");
        handleTrouble.call110("有人打架了,快来人");
        System.out.println("-------------------");
    }
}

输出结果:

救命啊,杀人啦,快来人啊~~~~~
刑警出动...
-------------------
XX大楼起火了
转接火警...
火警出动...
-------------------
有人打架了,快来人
民警出动...
-------------------

总结:

上面的例子有一点策略模式的影子,不过两个设计模式的侧重点不一样。
策略模式侧重的是将具体算法和客户端分离,使得易于扩展且算法之前可以互相替换。
外观模式侧重的是减少各个模块之间的耦合,使代码满足迪米特法则/最少知识法则,使不需要互相通信的双方都不必"认识"对方,不需要知道对方的任何细节,甚至可以不知道对方的存在,只需要通过中间方——即这里所指的外观类/门面类通信即可,
这个模式感觉也很常见。像我们去调用腾讯阿里的接口的时候都是不知道他们内部是怎么具体处理的。
书中也说到何时使用外观模式,下面整理一下:
首先,在设计初期阶段,应该要有意识的将不同的两层分离。(比如我们熟悉的MVC,业务逻辑层就是另外双方的Facade)
其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但是给外部调用他们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。
第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时可以在新系统和老系统之间建立一个外观Facade类。
 
posted @ 2019-04-12 22:30  莫愆  阅读(366)  评论(0编辑  收藏  举报