门面模式(Facade Pattern)

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了门面模式(Facade Pattern)相关的知识,希望对你有一定的参考价值。

门面模式(Facade Pattern)

门面模式的定义

也称为外观模式。要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

门面模式的结构

  • Facade门面角色

为多个子系统对外提供一个共同的接口。此角色知晓子系统的所有功能和责任。本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类。

  • subsystem子系统角色

实现系统的部分功能,客户可以通过外观角色访问它。可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户端而已。

门面模式的优点

  • 减少了系统之间的项目依赖

    1. 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
    2. 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
    3. 降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。
  • 提供灵活性

    不管子系统内部如何变化,只要不影响到门面对象,任你自由活动。

  • 提高安全性

    想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,不可访问到。

门面模式的缺点

  • 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

  • 不能很好地限制客户使用子系统类,很容易带来未知风险。

门面模式的实现

通用实现

public class ClassA {
    public void doSomethingA() {
        System.out.println("A想干些事情");
    }
}
public class ClassB {
    public void doSomethingB() {
        System.out.println("B想干些事情");
    }
}
public class ClassC {
    public void doSomethingC() {
        System.out.println("C想干些事情");
    }
}
public class GeneralFacade {
    private final ClassA a = new ClassA();
    private final ClassB b = new ClassB();
    private final ClassC c = new ClassC();

    public void methodA() {
        this.a.doSomethingA();
    }

    public void methodB() {
        this.b.doSomethingB();
    }

    public void methodC() {
        this.c.doSomethingC();
    }
}
public class Facade2 {
    private GeneralFacade generalFacade = new GeneralFacade();

    /**
     * 对外提供唯一的访问子系统的方法
     */
    public void methodB() {
        this.generalFacade.methodB();
    }
}
public static void main(String[] args) {
    GeneralFacade generalFacade = new GeneralFacade();
    generalFacade.methodA();
    generalFacade.methodB();
    generalFacade.methodC();
    Facade2 g = new Facade2();
    g.methodB();
}

邮件案例

public interface ILetterProcess {
    /**
     * 首先要写信的内容
     */
    public void writeContext(String context);

    /**
     * 其次写信封
     */
    public void fillEnvelope(String address);

    /**
     * 把信放到信封里
     */
    public void letterInotoEnvelope();

    /**
     * 然后邮递
     */
    public void sendLetter();
}
public class LetterProcessImpl implements ILetterProcess {
    /**
     * 首先要写信的内容
     *
     */
    @Override
    public void writeContext(String context) {
        System.out.println("填写信的内容..." + context);
    }

    /**
     * 其次写信封
     */
    @Override
    public void fillEnvelope(String address) {
        System.out.println("填写收件人地址及姓名..." + address);
    }

    /**
     * 把信放到信封里
     */
    @Override
    public void letterInotoEnvelope() {
        System.out.println("把信放到信封中...");
    }

    /**
     * 然后邮递
     */
    @Override
    public void sendLetter() {
        System.out.println("邮递信件...");
    }
}
public class Police {
    /**
     * 检查信件,检查完毕后警察在信封上盖个戳:此信无病毒
     */
    public void checkLetter(ILetterProcess letterProcess) {
        System.out.println(" 信件已经检查过了...");
    }
}
public class ModenPostOffice {

    private final ILetterProcess letterProcess = new LetterProcessImpl();

    private final Police letterPolice = new Police();

    /**
     * 写信,封装,投递,一体化
     */
    public void sendLetter(String context, String address) {
        letterProcess.writeContext(context);
        letterProcess.fillEnvelope(address);
        letterPolice.checkLetter(letterProcess);
        letterProcess.letterInotoEnvelope();
        letterProcess.sendLetter();
    }
}
public static void main(String[] args) {
    //现代化的邮局,有这项服务,邮局名称叫Hell Road
    ModenPostOffice hellRoadPostOffice = new ModenPostOffice();
    //定义一个地址
    String address = "Happy Road No. 666,God Province,Heaven";
    //信的内容
    String context = "Hello,It's me,do you know who I am? I'm your old lover. ";
    hellRoadPostOffice.sendLetter(context, address);
}

门面模式的使用场景

通常在以下情况下可以考虑使用外观模式。

  1. 为一个复杂的模块或子系统提供一个供外界访问的接口。
  2. 子系统相对独立——外界对子系统的访问只要黑箱操作即可。
  3. 预防低水平人员带来的风险扩散。
  4. 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。

门面模式的注意事项

  • 一个子系统可以有多个门面
    1. 门面已经庞大到不能忍受的程度
    2. 子系统可以提供不同访问路径
  • 门面不参与子系统内的业务逻辑

本文主要参考:

  1. 《C语言中文网》设计模式的相关内容
  2. 《设计模式之禅》第二版 秦小波

以上是关于门面模式(Facade Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

门面模式(Facade Pattern)

门面模式-Facade Pattern(Java实现)

外观模式(Facade Pattern)

设计模式之- 外观模式(Facade Pattern)

外观模式(Facade Pattern)

12外观模式(Facade Pattern)