23种设计模式之外观模式
目录
- 1. 简介
- 2. 代码
- 2.1 SelectFoodService (选择食品)
- 2.2 PayService (支付服务)
- 2.3 TakeService (制作服务)
- 2.4 OrderService (下单服务)
- 2.5 Food (食品)
- 2.6 TackingSystem (外观类)
- 2.7 Test (测试类)
- 3. 优缺点
- 3. 总结
1. 简介
外观模式是一种结构型设计模式。它为子系统中的一组接口提供了一个统一的高层接口,这个高层接口使得子系统更容易使用。就好像给一个复杂的机器(子系统)安装了一个简单的控制面板(外观类),用户通过操作这个控制面板就能轻松地使用机器的各种功能,而不需要了解机器内部复杂的结构和各个部件(子系统中的接口)是如何协同工作的。
例如,考虑一个计算机系统,它包含了 CPU、硬盘、内存等多个组件,每个组件都有自己复杂的操作接口。通过外观模式,可以创建一个 “计算机启动” 外观类,它内部封装了 CPU 初始化、硬盘加载系统文件、内存自检等操作。用户只需要调用 “计算机启动” 这个简单的操作,而不用去分别调用每个组件的复杂操作。
外观模式的结构组成
- 外观类(
Facade Class
)
这是外观模式的核心。外观类知道哪些子系统类负责处理请求,并将客户的请求代理给适当的子系统对象。它简化了与子系统的交互方式,对外提供了一个更加简单、统一的接口。例如,在上述计算机启动的例子中,“计算机启动” 类就是外观类。 - 子系统类(
Sub - system Classes
)
这些是实现具体功能的类,它们各自负责一个特定的、复杂的功能部分。在计算机系统中,CPU 类、硬盘类、内存类等都是子系统类。它们本身的操作可能很复杂,但外观类会对它们进行整合,使得用户不需要直接接触这些复杂的操作。
2. 代码
这里用点餐系统举例子。
2.1 SelectFoodService (选择食品)
public class SelectFoodService {
public void select(String foodName){
System.out.println("正在选择" + foodName + "。。。");
}
}
2.2 PayService (支付服务)
public class PayService {
public void pay(){
System.out.println("正在支付。。。");
}
public boolean checkBanlance(){
System.out.println("正在检查用户余额。。。");
return true;
}
}
2.3 TakeService (制作服务)
public class TakeService {
public void taking(){
System.out.println("正在制作外卖。。。");
}
}
2.4 OrderService (下单服务)
public class OrderService {
public void makeOrder(){
System.out.println("正在下单。。。");
}
}
2.5 Food (食品)
public class Food {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.6 TackingSystem (外观类)
public class TackingSystem {
private SelectFoodService selectFoodService;
private PayService payService;
private OrderService orderService;
private TakeService takeService;
public TackingSystem(){
selectFoodService = new SelectFoodService();
payService = new PayService();
orderService = new OrderService();
takeService = new TakeService();
}
public void orderTacking(Food food){
// 点餐
selectFoodService.select(food.getName());
// 校验余额
boolean isPay = payService.checkBanlance();
// 支付
if(isPay){
payService.pay();
takeService.taking();
orderService.makeOrder();
}
}
}
2.7 Test (测试类)
public class Test {
public static void main(String[] args) {
Food food = new Food();
food.setName("西红柿鸡蛋面");
TackingSystem tackingSystem = new TackingSystem();
tackingSystem.orderTacking(food);
}
}
输出结果:
正在选择西红柿鸡蛋面。。。
正在检查用户余额。。。
正在支付。。。
正在制作外卖。。。
正在下单。。。
3. 优缺点
外观模式的优点
- 简化接口
为复杂的子系统提供了一个简单的、统一的接口,降低了客户端与子系统之间的耦合度。客户端只需要和外观类交互,不需要了解子系统内部的复杂细节,就像在家庭影院系统中,用户只需要通过外观类的 “watchMovie” 和 “endMovie” 方法就能轻松控制整个系统,而不用分别去操作每个设备。 - 提高可维护性和可扩展性
当子系统内部的结构和功能发生变化时,只要外观类的接口保持不变,客户端代码就不需要修改。例如,如果要升级 DVD 播放器的内部软件,只要它的 “turnOn” 和 “turnOff” 接口不变,外观类和客户端代码都不需要调整。同时,新的子系统可以很容易地添加到外观类中,方便系统的扩展。 - 实现了层次隔离
外观模式可以将系统的高层逻辑和底层实现分离开来。高层逻辑通过外观类来体现,底层的子系统则负责具体的功能实现。这种层次隔离使得代码的结构更加清晰,便于不同层次的开发人员分别进行开发和维护。
外观模式的缺点
- 不符合开闭原则的潜在风险
如果外观类的接口需要修改,可能会影响到所有使用该外观类的客户端。因为外观类是客户端和子系统之间的桥梁,一旦这个桥梁的接口发生变化,就可能需要修改客户端代码。例如,如果要在家庭影院系统的外观类中添加一个新的功能,如 “暂停电影”,那么所有使用这个外观类的客户端代码可能都需要相应地修改,这在一定程度上不符合开闭原则(对扩展开放,对修改关闭)。 - 外观类可能会变得过于复杂
如果子系统本身非常庞大和复杂,外观类需要整合大量的子系统接口,那么外观类可能会变得臃肿和复杂。这可能会导致外观类的维护成本增加,而且可能会降低代码的可读性。例如,一个大型企业级软件系统的外观类,如果要整合众多的子系统,如数据库管理系统、消息队列系统、文件存储系统等,外观类的代码可能会变得非常复杂。
3. 总结
其实就是定义多个子系统,一个总系统,随后总系统初始化多个子系统,然后使用就行了。