设计模式之门面模式

门面模式

定义

门面模式( Facade Pattern) 也叫作外观模式, 是一种比较经常使用的封装模式, 其定义以下:设计模式

Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.( 要求一个子系统的外部与其内部的通讯必须经过一个统一的对象进行。 门面模式提供一个高层次的接口, 使得子系统更易于使用。 )安全

角色

  • Facade 门面角色

    这个角色没有没有实际的业务, 而是一个委托类, 客户端调用这个此角色的方法, 此角色会将客户端的请求委派给相应的的子系统中, 客户端不须要在乎子系统的实现细节.ide

  • subSystem子系统角色

    一个门面能够拥有一个或者多个子系统, 一个子系统不是单独的一个类, 而是一个类的集合. 子系统并不知道门面的存在, 对于子系统来讲, 门面只是另外一个客户端而已.spa

实例 - 我要写情书

咱们要用最浪漫最原始的方式去表白, 写一份情书!设计

写情书过程的接口和实现

定义写信过程的借口:code

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

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

    // 把信放到信封
    public void letterIntoEnvelope();

    // 邮递
    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 letterIntoEnvelope() {
        System.out.println("把信放到信箱中...");
    }

    @Override
    public void sendLetter() {
        System.out.println("邮递信件... ");
    }
}

开始告白

为了告白, 咱们须要四个步骤, 对应写信接口的四个方法, 并且这个四个方法是须要按照顺序的, 不能颠倒:接口

public class Client {
    public static void main(String[] args) {
        ILetterProcess process = new LetterProcessImpl();

        process.writeContext("你好, 我喜欢你!");
        process.fillEnvelope("宁波市江北区风华路201号宁波工程学院, xb");
        process.letterIntoEnvelope();
        process.sendLetter();
    }
}

运行结果:rem

填写信的内容... 你好, 我喜欢你!
填写收件人地址及姓名... 宁波市江北区风华路201号宁波工程学院, xb
把信放到信箱中...
邮递信件...

可是这样会有一点问题, 首先咱们必需要知道它们的顺序, 若是顺序出现错误, 则达不到预期的目标, 这样的写法不符合迪米特法则和接口隔离原则. 并且, 若是要同时要和不少女孩子表白(雾, 这是什么操做)的话, 每次都要这样, 累的要死. 好在如今邮局推出一个代写情书的服务, 只要提供信的内容和地址收信人就好了, 其余的步骤邮局会完成的(雾, 告白能不能有点诚意), 很是好:it

public class Facade {
    private ILetterProcess process = new LetterProcessImpl();

    public void sendLetter(String context, String address) {
        process.writeContext(context);
        process.fillEnvelope(address);
        process.letterIntoEnvelope();
        process.sendLetter();
    }
}

有了这种人性化的服务, 咱们就能更方便的写信了:

Facade facade = new Facade();
String context = "你好, 我喜欢你!";
String address = "宁波市江北区风华路201号宁波工程学院, xb";
facade.sendLetter(context, address);

结果是和上面一致的, 可是更加简化了, 咱们只须要提供内容和地址就好了, 其余什么都不用去管, 并且易于扩展.

如今, 邮局须要核查信件是否安全, 须要进行审查, 因此咱们须要对Facade进行扩展:

public class Police {
    public void checkLetter(ILetterProcess process) {
        System.out.println(process + " 信件已经审查...");
    }
}
public class Facade {
    private ILetterProcess process = new LetterProcessImpl();
    private Police police = new Police();
    public void sendLetter(String context, String address) {
        process.writeContext(context);
        process.fillEnvelope(address);
        process.letterIntoEnvelope();
        police.checkLetter(process);
        process.sendLetter();
    }
}

而后再执行一次Client:

填写信的内容... 你好, 我喜欢你!
填写收件人地址及姓名... 宁波市江北区风华路201号宁波工程学院, xb
把信放到信箱中...
io.ride.facade_pattern.LetterProcessImpl@61bbe9ba 信件已经审查...
邮递信件...

Client程序并无作出任何修改, 可是能够看到已经增长了审查信件的步骤.

门面模式的优势

  • 减小系统的相互依赖

    门面模式里全部的依赖都是对门面对象的依赖, 与子系统没有关系

  • 提升了灵活性

    无论子系统内部如何变化, 只要不影响到门面对象,对客户端来讲就是没有变化. 灵活性提升了.

  • 提升安全性

    想要访问子系统的业务系统, 必须经过门面系统来访问, 不然没法访问.

门面系统的缺点

无论子系统内部如何变化, 只要不影响到门面对象,若是门面对象出现错误,那么只有修改门面角色的代码.

使用场景

  • 为一个复杂的模块或子系统提供一个供外界访问的接口
  • 子系统相对独立——外界对子系统的访问只要黑箱操做便可
  • 预防低水平人员带来的风险扩散

参考资料

  1. 设计模式之禅
相关文章
相关标签/搜索