本篇讲解Java设计模式中的外观模式,分为定义、模式应用前案例、结构、模式应用后案例、适用场景、模式可能存在的困惑和本质探讨7个部分。
外观模式是为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
在新的分类方式中,外观模式被划分至类之间的交互类别中,其简化的是一个类与一组类之间的交互耦合问题。
在外观模式中,列举一个电商领域的案例。先来看一下未使用外观模式前的代码实现。
电商领域通常包括库存子系统、支付子系统和物流子系统,代码如下。
public class InventorySystem {//库存子系统 public void updateInventory(String product, int quantity) { System.out.println("Updating inventory for " + product + ": " + quantity); }}public class PaymentSystem {//支付子系统 public void processPayment(double amount) { System.out.println("Processing payment: $" + amount); }}public class ShippingSystem {//物流子系统 public void shipOrder(String address) { System.out.println("Shipping order to address: " + address); }}
调用方代码如下。
public class Client {//调用方代码 public static void main(String[] args) { InventorySystem inventory = new InventorySystem(); PaymentSystem payment = new PaymentSystem(); ShippingSystem shipping = new ShippingSystem(); inventory.updateInventory("Computer", 1); payment.processPayment(1500); shipping.shipOrder("123 Main Street"); }}
在上述代码中,不难发现,调用方与各个子系统直接耦合,这样主要带来两个问题。
一个问题是调用方需要知晓每一个子系统的细节。在某些情况下,这些子系统之间的关系也需要知晓。
另一个问题是如果子系统代码发生变更,调用方代码也需要受到关联影响。
外观模式的示例代码如下。
public class SubSystemOne { public void MethodOne() { System.out.println("Called SubSystemComponentOne's methodOne()"); }}public class SubSystemTwo { public void MethodTwo() { System.out.println("Called SubSystemComponentTwo's MethodTwo()"); }}public class SubSystemThree { public void MethodThree() { System.out.println("Called SubSystemComponentThree's methodThree()"); }}public class SubSystemFour { public void MethodFour() { System.out.println("Called SubSystemComponentFour's MethodFour()"); }}public class Facade { private SubSystemOne componentOne; private SubSystemTwo componentTwo; private SubSystemThree componentThree; private SubSystemFour componentFour; public Facade() { componentOne = new SubSystemOne(); componentTwo = new SubSystemTwo(); componentThree = new SubSystemThree(); componentFour = new SubSystemFour(); } public void MethodA() { componentOne.MethodOne(); componentTwo.MethodTwo(); componentThree.MethodThree(); } public void MethodB() { componentTwo.MethodTwo(); componentThree.MethodThree(); componentFour.MethodFour(); }}public class Client { public static void main(String[] args) { Facade facade = new Facade(); // 客户端只需要调用外观类提供的接口 facade.MethodA(); facade.MethodB(); }}
上述电商领域的案例,在应用外观模式之后的代码实现如下。
库存子系统、支付子系统和物流子系统的代码不变。
public class InventorySystem {//库存子系统 public void updateInventory(String product, int quantity) { System.out.println("Updating inventory for " + product + ": " + quantity); }}public class PaymentSystem {//支付子系统 public void processPayment(double amount) { System.out.println("Processing payment: $" + amount); }}public class ShippingSystem {//物流子系统 public void shipOrder(String address) { System.out.println("Shipping order to address: " + address); }}
按照外观模式,增加了一个外观类。
public class OrderFacade {//订单外观类 private final InventorySystem inventory; private final PaymentSystem payment; private final ShippingSystem shipping; public OrderFacade() { this.inventory = new InventorySystem(); this.payment= new PaymentSystem(); this.shipping= new ShippingSystem(); } //提供一个简化方法来处理整个订单流程 public void placeOrder(String product, int quantity,double amount,String address){ this.inventory.updateInventory(product,quantity); this.payment.processPayment(amount); this.shipping.shipOrder(address); }}
最后,调用方代码修改如下。
public class Client { public static void main(String[] args) { //使用外观模式进行下单操作 OrderFacade facade= new OrderFacade(); facade.placeOrder("Computer", 1, 1500.00,"123 Main Street"); }}
可以看到,代码的复杂性已经挪到外观类中实现,调用方代码变得非常简洁清晰。
外观模式适用于以下场景:
1、多个子系统或接口需要通过一定的交互共同为调用方服务,如果希望子系统后续可以相对调用方独立进行演进,可以考虑外观模式
2、需求实现新功能时,需要依赖企业中的遗留系统的功能。由于遗留系统通常后续会安排下线。此时就不建议将遗留系统的接口直接对调用方暴露,而是在一个外观类中封装新增加的功能和遗留系统功能
困惑1:外观模式定义中提到的“界面”,具体是什么含义?
在外观模式中,多个子系统属于一个大的系统。界面可以理解为这个大系统对外暴露的契约接口。调用方只能通过界面来与系统进行交互。
对于一个系统来讲,对外暴露清晰简洁的接口是非常有必要的。这不仅可以节省与调用方的沟通成本,也可以与调用方相对解耦,以便后续独立进行演进。
在系统建设初期,和调用方会制定契约接口。但是随着系统功能越来越多,经常会发现调用方需要依赖的接口越来越多,此时就可以将相互有关系的接口,再通过外观类这一层进行再封装,始终保持对外的简洁性。
此外,在外观模式下,外观类通常并不新增功能,仅仅是封装已有多个子系统的交互关系。
本文链接:http://www.28at.com/showinfo-26-87982-0.html一文彻底搞明白外观模式
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 优化代码性能:C#中轻松测量执行时间