结构型 - 外观
提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。
public class SubSystem {public void turnOnTV() {System.out.println("turnOnTV()");}public void setCD(String cd) {System.out.println("setCD( " + cd + " )");}public void starWatching(){System.out.println("starWatching()");}
}
public class Facade {private SubSystem subSystem = new SubSystem();public void watchMovie() {subSystem.turnOnTV();subSystem.setCD("a movie");subSystem.starWatching();}
}public class Client {public static void main(String[] args) {Facade facade = new Facade();facade.watchMovie();}
}
使用的场景?
简化复杂系统:当系统内部由多个子系统组成,并且这些子系统之间相互依赖,外观模式可以提供一个统一的入口,简化使用。
解耦客户端和子系统:当客户端需要与多个子系统交互时,使用外观模式可以减少客户端对子系统的直接依赖,降低耦合度。
隐藏实现细节:当系统内部的实现经常变化,而希望客户端代码尽量少受影响时,可以使用外观模式隐藏这些变化。
提供统一接口:对外暴露一个简单、稳定的接口,避免让用户直接面对复杂的底层系统本质是什么?
外观模式的本质是 封装复杂性,提供统一访问接口。它通过创建一个“门面”(Facade)类,封装多个子系统的调用,使得客户端可以通过这个门面类来访问系统,而不需要了解系统的复杂内部结构。它解决了什么问题?
外观模式主要解决 降低复杂系统的使用难度和客户端的依赖性。
降低耦合:客户端不需要直接依赖多个子系统,而是通过外观类进行交互。
提高可维护性:当子系统发生变化时,只需要修改外观类,而不需要修改所有使用子系统的代码。
增强可读性:提供一个统一的、高层次的接口,使得代码更清晰、更易理解。它体现了设计模式中什么原则?
迪米特法则(最少知道原则,LoD):外观模式减少了对象之间的直接交互,客户端只需要知道外观类,而不需要了解具体的子系统。
单一职责原则(SRP):外观类的职责是提供一个简化的接口,而不是处理子系统的业务逻辑。
依赖倒置原则(DIP):高层模块(客户端)不应该依赖低层模块(子系统),而是通过外观类进行依赖。存在的缺陷?
可能导致“上帝类”:如果外观类封装过多逻辑,可能会变得过于庞大,形成“上帝类”(God Object),降低可维护性。
降低灵活性:如果客户端需要访问子系统的某些高级功能,而外观类没有提供接口,那么客户端仍然需要直接访问子系统,削弱了外观模式的意义。
可能引入性能问题:如果外观类封装了过多的子系统调用,而每次客户端调用外观类时都会触发所有子系统调用,可能会降低性能。你认为与它相关的设计模式有哪些? 它们之间的区别有哪些?
中介者模式(Mediator):
相似点:都用于降低对象之间的直接交互,提高模块解耦性。
区别:外观模式是为多个子系统提供统一入口,而中介者模式则是管理多个对象之间的交互关系,通常用于对象之间的通信,而非子系统之间的封装。适配器模式(Adapter):
相似点:都对现有系统进行了封装,以提供更方便的使用方式。
区别:适配器模式用于接口转换,使不兼容的接口能够协同工作,而外观模式只是提供一个简化的接口,并不改变子系统的行为。代理模式(Proxy):
相似点:都为客户端提供了一个间接访问的方式。
区别:代理模式通常用于控制对某个对象的访问,例如增加权限控制、缓存,而外观模式的主要目的是简化接口。*开源架构中哪些使用了这一模式?
Spring Framework
Spring 的 JdbcTemplate 就是外观模式的一个例子,它封装了 JDBC 的底层复杂逻辑,使得开发者可以更简单地执行 SQL 语句。
RestTemplate 也是外观模式,它对 HTTP 客户端进行封装,使得调用 REST API 变得简单。MyBatis
SqlSession 作为外观类,封装了底层数据库操作,使得开发者可以通过一个简单的 API 进行数据库查询。Dubbo
Dubbo 的 ServiceProxy 代理远程调用细节,对外提供一个简洁的调用方式。Log4j/SLF4J
SLF4J 是日志框架的外观模式,它统一了 Log4j、Logback 等日志实现,提供一个统一的 API,减少了对具体日志实现的依赖。