[白话设计模式] 外观模式 Facade pattern

275 阅读4分钟

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

白话一下

话说毕业后在职场打拼多年的郭靖,在襄阳按揭买的房终于交房了,想着和女朋友黄蓉在新房里完婚的场景,内心激动万分。突然想起毛坯房还没装修不能入住,不由从梦中惊醒。远房表叔柯镇恶曾经干过装修队,于是郭靖马上拨通了他的电话。柯镇恶告诉了他很多门道,让他自己去买材料,再找几个装修工人来施工,这样可以省不少钱,郭靖点头称是。

到了周末郭靖拉上女朋友,兴高采烈直奔建材市场而去。然而逛了一天下来,发现要买的材料种类太多,价格也高低不一,要买齐所有材料,对一个装修小白来说就已经很不容易了,更别说还想要价廉物美了。两人愁容满面的走出了建材市场。

正在门口苦恼的郭靖,眼前走过一个熟悉的身影,这不是多年不见的发小杨康吗?他一把叫住杨康,一番寒暄之后,发现杨康开了一家装修公司,据杨康说可以为客户提供一站式服务,正好可以解决郭靖的苦恼。最终郭靖决定把装修的事委托给杨康来办。

杨康请公司首席设计师穆念慈定制了图纸,又从建材商欧阳克等处进了上好的材料,最后请了梅超风等手艺精湛的老师傅,为郭靖的新房装修了一番。郭靖从头至尾只和杨康打交道,省却了不少烦恼。最后,装修如期完工,郭靖黄蓉也如期完婚,两人从此过上了幸福快乐的生活。

说正经的

什么是外观模式?

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

从故事中我们很容易发现,外观模式的目的是降低系统复杂度,从而提高客户端调用的便捷性。它非常符合迪米特法则,即一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。郭靖只要和杨康说话,根本不用管他背后的梅超风、欧阳克之类的。

UML类图如下:

image.png

优点

  • 对客户来说,使用变得更加简便,客户端的代码也更简单。自从遇上杨康之后,郭靖从此省心了不少。
  • 客户端和子系统之间实现了松耦合关系。如果有一天梅超风不干了,杨康只需要请另一位师傅丘处机来施工,不会影响到郭靖。

缺点

  • 外观模式最大的缺点在于违背了“开闭原则”,当增加新的子系统或者移除子系统时需要修改外观类。可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。

适用场景

当系统非常复杂或难以理解时,开发人员通常会引入外观模式,因为系统有许多相互依赖的类,或者因为它的源代码不可用。这种模式隐藏了子系统的复杂性,并为客户端提供了更简单的接口。

代码演示

以上面UML类图为例,Java的代码实现如下:

public class Class1 {
    public void doStuff(Class2 c2) {
        // ...
    }
    public X getX() {
        return this.x;
    }
}

public class Class2 {
    // ...
}

public class Class3 {
    public void setX(X x) {
        // ...
    }
    public Y getY(){
        return this.y;
    }
}

public class Facade {
    public Y doSomething() {
        Class1 c1 = new Class1();
        Class2 c2 = new Class2();
        Class3 c3 = new Class3();
        c1.doStuff(c2);
        c3.setX(c1.getX());
        return c3.getY();
    }
}

public class Client1 {
    void doIt() {
        // ...
        Facade facade = new Facade();
        facade.doSomething();
    }
}

参考