简介

  • 设计模式类型 : 结构型 ;

  • 标准定义 : 提供一个统一接口 , 用于访问子系统中的一群接口 ;

  • 隐藏复杂性目的 : 定义高层级接口 , 让子系统更容易使用 , 目的是隐藏系统的复杂性 ;

  • 交互流程 : 多个子系统联合完成一个操作 , 提供一个统一的接口 , 供客户端调用 , 客户端不与每个子系统进行复杂的交互 , 客户端只与提供接口的外观类进行交互 ;

主要组成部分:

  • 外观类(Facade Class):外观类是客户端与系统交互的入口点。它包含了系统的子系统接口,负责将客户端请求委派给适当的子系统。

  • 子系统(Subsystems):子系统是系统中的组件或模块,用于完成特定的任务或功能。外观模式将多个子系统封装在外观类中。

工作流程

  • 客户端通过外观类访问系统,向外观类发起请求。

  • 外观类内部根据请求的类型,将请求委派给适当的子系统。

  • 子系统执行请求,并返回结果给外观类。

  • 外观类将结果返回给客户端。

例子

结构

代码

外观Facade类

/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public class SmartHomeFacade {
    private LightSystem lightSystem;
    private AudioSystem audioSystem;
    private TemperatureSystem temperatureSystem;

    public SmartHomeFacade(){
        this.audioSystem = new AudioSystem();
        this.lightSystem = new LightSystem();
        this.temperatureSystem = new TemperatureSystem();
    }

    public void leaveHome(){
        this.audioSystem.stopMusic();
        this.lightSystem.turnOff();
        this.temperatureSystem.setTemperature(30);
        System.out.println("离家模式");
    }

    public void returnHome(){
        this.audioSystem.playMusic();
        this.lightSystem.turnOn();
        this.temperatureSystem.setTemperature(26);
        System.out.println("回家模式");
    }
}

具体子系统

/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public class AudioSystem {

    public void playMusic(){
        System.out.println("开始播放音乐");
    }

    public void stopMusic(){
        System.out.println("关闭音乐");
    }
}

public class LightSystem {

    public void turnOn(){
        System.out.println("灯光已打开");
    }

    public void turnOff(){
        System.out.println("灯光已关闭");
    }
}

public class TemperatureSystem {
    public void setTemperature(int temperature){
        System.out.println("温度已经设置为"+temperature+"摄氏度");
    }
}

测试类

/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public class FacadePatternTest {
    public static void main(String[] args) {
        SmartHomeFacade sm = new SmartHomeFacade();
        sm.leaveHome();
        sm.returnHome();
    }
}

应用

在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。

外观模式优缺点

  • 优点:
    • 简化接口:外观模式提供了一个简化的接口,隐藏了系统的复杂性,使客户端更容易使用系统。

    • 解耦:外观模式将客户端与子系统之间的依赖关系解耦,客户端只需与外观类交互,而不需要了解子系统的内部结构。

    • 提高安全性:外观模式可以限制客户端直接访问子系统的某些部分,从而提高系统的安全性。

    • 降低学习成本:外观模式使系统更易于理解,减少了学习和使用系统所需的时间和精力。

    • 遵循单一职责原则:外观模式有助于确保每个类只负责特定的任务,遵循单一职责原则。

    • 符合迪米特法则 : 最少知道原则 , 用户不需要了解子系统内部的情况 , 也不需要与子系统进行交互 , 只与外观类进行交互 ; 降低了应用层与子系统之间的耦合度 ;

  • 缺点:

    • 不适用于所有情况:外观模式并不适用于所有系统,特别是当需要访问子系统的更多细节或进行复杂的自定义操作时,可能会显得不足够灵活。

    • 增加新功能困难:如果需要添加新的子系统或修改现有子系统,可能需要修改外观类,这可能会导致外观类变得复杂。

    • 不提供完全的封装:外观模式通常无法完全封装子系统的复杂性,某些复杂的系统细节可能仍然对外可见。

门面模式和代理模式区别

门面模式就是特殊的静态代理

他们强调的不一样
门面模式强调的是封装,调用多个子系统,提供一个统一的接口,
代理模式强调的是增强

7 大设计原则

不能全部遵守 , 也不能不遵守 , 注意平衡 功能 和 系统复杂度 , 找到最合适的一个点 ;

- 单一职责原则(Single Responsibility Principle - SRP):
这个原则规定一个类应该只有一个改变的理由,也就是说,一个类应该只有一个单一的职责。这有助于保持类的简单性和可维护性,因为每个类只需关注一个特定的功能。

- 开放-封闭原则(Open-Closed Principle - OCP):
开放-封闭原则要求系统中的软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改原有代码。

- 里氏替换原则(Liskov Substitution Principle - LSP):
里氏替换原则规定,子类应该能够替换其父类,而不会影响程序的正确性。也就是说,子类应该继承父类的行为,但可以扩展或修改该行为,但不应该改变父类的行为。

- 接口隔离原则(Interface Segregation Principle - ISP):
接口隔离原则要求一个类不应该强迫其客户端依赖于它们不需要的接口。应该根据客户端的需求定义小而精确的接口,而不是大而笨重的接口。

- 依赖倒置原则(Dependency Inversion Principle - DIP):
依赖倒置原则要求高级模块不应该依赖于低级模块,它们都应该依赖于抽象。具体来说,这意味着应该通过抽象接口或抽象类来定义模块之间的依赖关系,而不是直接依赖于具体实现。

- 迪米特法则(Law of Demeter - LoD):
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

- 合成复用原则(Composite Reuse Principle - CRP):
合成复用原则鼓励通过组合(合成)已有的类来实现新功能,而不是通过继承现有的类。这样可以降低系统的耦合度,并且更加灵活。

源码位置

全部源码github.com/xs-alpha/designPattern

参考文献

如有内容侵权,麻烦联系博主删除

站点统计

  • 文章总数:315 篇
  • 分类总数:20 个
  • 标签总数:193 个
  • 运行天数:1126 天
  • 访问总数:10823 人次

浙公网安备33011302000604

辽ICP备20003309号