github:GitHub - QiuliangLee/pattern: 设计模式
1 什么是门面设计模式
门面设计模式是一种软件设计模式,也被称为外观(Facade)模式。它提供了一个简单的接口,让客户端能够访问复杂系统中的一组接口。通过门面模式,我们可以隐藏系统的复杂性,并提供一个简单的接口来访问系统。此外,门面模式还可以帮助我们解耦系统中的各个模块,从而提高系统的可维护性和可测试性。
增加一层
提供一个高层次的接口,使得子系统更易于使用
2 为什么需要门面设计模式
需求:电商场景下,需要各个模块的汇总报表,这里只写了三个,真实场景下很多。
//订单系统
public class OrderSys {public String getOrderNum(){System.out.println("获取订单号");return "123456";}
}
//支付系统
public class PaymentSys {private OrderSys orderSys;public PaymentSys(OrderSys orderSys) {this.orderSys = orderSys;}public BigDecimal getOrderAccount(String orderNum){System.out.println(String.format("获取%s订单支付金额",orderNum));return BigDecimal.valueOf(500);}
}
//物流系统
public class DeliverySys {public int getDeliveryTime(){System.out.println("获取配送耗时");return 30*60;//30分钟}
}
client
package com.lql.facade;public class Client {public static void main(String[] args) {OrderSys orderSys = new OrderSys();PaymentSys paymentSys = new PaymentSys(orderSys);DeliverySys deliverySys = new DeliverySys();final String orderNum = orderSys.getOrderNum();System.out.println(String.format("\n报表\n--------------------------------------------\n" +"订单号:%s | 金额:%s元 | 配送耗时:%s分钟",orderNum,paymentSys.getOrderAccount(orderNum).toPlainString(),deliverySys.getDeliveryTime() / 60));}
}
缺点:
1.客户端难以使用:如果系统中有很多复杂的子系统,客户端就需要了解每一个子系统的实现细节,这会增加客户端的使用难度和学习成本。
比如我要是想使用报表服务,就需要知道订单服务,物流服务,支付服务等等。
2.系统之间的耦合度高:如果子系统的实现发生变化,客户端也需要相应地修改自己的代码来适应变化,这会增加系统之间的耦合度,降低系统的灵活性和可维护性。
订单服务,物流服务,支付服务任何一个服务改变,我这里的报表服务就要改代码,
3.代码冗余:如果多个客户端都需要访问同一个子系统,那么每个客户端都需要编写相同的代码来访问该子系统,这会增加代码冗余和维护成本。
3. 门面模式
ReportFacade
package com.lql.facade;public class ReportFacade {public void generateReport() {OrderSys orderSys = new OrderSys();PaymentSys paymentSys = new PaymentSys(orderSys);DeliverySys deliverySys = new DeliverySys();final String orderNum = orderSys.getOrderNum();System.out.println(String.format("\n报表\n--------------------------------------------\n" +"订单号:%s | 金额:%s元 | 配送耗时:%s分钟",orderNum,paymentSys.getOrderAccount(orderNum).toPlainString(),String.valueOf(deliverySys.getDeliveryTime() / 60)));}
}
Client
package com.lql.facade;public class Client {public static void main(String[] args) {ReportFacade reportFacade = new ReportFacade();reportFacade.generateReport();}
}
4. 应用场景
1. DDD中apliication层用来编排各个domain service的接口就是借鉴了门面设计思想。
2. MyBatis 中的Configuration 去创建MetaObject 对象使用到外观模式