Java设计模式——外观模式
⚪外观模式(Facade)是一种结构型设计模式,外观模式通过引入一个外观类来隐藏系统的复杂性,使客户端不需要了解子系统的内部工作细节。
⚪意图:为复杂的子系统提供一个简化的接口,以便客户端可以更容易地与子系统交互。
⚪以下是工厂方法模式的关键要点:
▷ 角色和责任:
- 外观(Facade):这是外观模式的核心,提供了一个简化的接口,它知道如何与一个或多个子系统进行交互。外观将客户端的请求委派给适当的子系统对象。
- 子系统(Subsystem):子系统是完成实际工作的一组类或对象。外观模式的目标是将客户端与这些子系统的复杂性隔离开来。
▷ 工作流程:
- 客户端通过外观类访问子系统。
- 外观类将客户端的请求转发给一个或多个子系统。
- 子系统执行请求,并将结果返回给外观类。
- 外观类将结果返回给客户端。
▷ 示例
// 子系统:音响系统
class Amplifier {
void on() {
System.out.println("Amplifier is on");
}
void setVolume(int volume) {
System.out.println("Setting volume to " + volume);
}
}
// 子系统:投影仪
class Projector {
void on() {
System.out.println("Projector is on");
}
void setInput(String input) {
System.out.println("Setting input to " + input);
}
}
// 子系统:DVD 播放器
class DVDPlayer {
void on() {
System.out.println("DVD Player is on");
}
void play(String movie) {
System.out.println("Playing movie: " + movie);
}
}
// 外观类:家庭影院外观
class HomeTheaterFacade {
private Amplifier amplifier;
private Projector projector;
private DVDPlayer dvdPlayer;
public HomeTheaterFacade(Amplifier amp, Projector projector, DVDPlayer dvd) {
this.amplifier = amp;
this.projector = projector;
this.dvdPlayer = dvd;
}
void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
amplifier.on();
amplifier.setVolume(5);
projector.on();
projector.setInput("DVD");
dvdPlayer.on();
dvdPlayer.play(movie);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 创建子系统对象
Amplifier amplifier = new Amplifier();
Projector projector = new Projector();
DVDPlayer dvdPlayer = new DVDPlayer();
// 创建外观对象
HomeTheaterFacade facade = new HomeTheaterFacade(amplifier, projector, dvdPlayer);
// 使用外观启动电影
facade.watchMovie("The Shawshank Redemption");
}
}
⚪适用性
- 要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类,这使得子系统更具有可重用性,也更容易对子系统进行定制,但也给那些不需要定制子系统的用户带米一些使用上的困难。Facade 可以提供一个简单的默认视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过 Facade 层。
- 客户程序与抽象类的实现部分之间存在若很大的依赖性。引入 Facade 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
- 当需要构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,则可以让它们仅通过 Facade 进行通信,从而简化了它们之间的依赖关系。
⚪应用场景
- 简化复杂系统的接口:当一个系统非常复杂,包含多个子系统或组件,而客户端希望能够以更简单的方式与系统交互时,外观模式非常有用。它提供了一个统一的接口,隐藏了系统内部的复杂性。
- 解耦客户端和子系统:外观模式可以将客户端与子系统解耦,使得客户端不需要了解子系统的内部结构,从而降低了耦合度。
- 提供更高级的接口:外观模式可以为客户端提供更高级别的接口,使得客户端更容易使用系统,而不必处理系统的底层细节。
⚪实际已有场景
- Java API中的应用:Java标准库中包含了许多使用外观模式的类和接口。例如,Java的网络通信API(如java.net包)提供了URLConnection类,它是一个外观,用于简化与各种网络协议的通信。客户端可以使用URLConnection来发送HTTP请求,而无需了解底层协议的复杂性。
- Spring框架中的应用:Spring框架本身使用了外观模式来隐藏底层的复杂性。例如,Spring的ApplicationContext接口就是一个外观,它简化了Spring容器的配置和使用,使得开发者可以更容易地管理依赖注入和应用程序的组件。
- Spring Security:Spring Security是Spring家族中的一个子项目,用于处理应用程序的安全性。它提供了一个外观,简化了身份验证和授权过程,使得开发人员可以更轻松地集成安全功能到他们的应用程序中。
- Spring Data:Spring Data是Spring家族中的另一个子项目,用于简化数据访问层的开发。它提供了外观类和接口,使得开发人员可以使用一种通用的方式与各种数据存储(如关系数据库、NoSQL数据库)进行交互,而不必关心底层数据访问的细节。