外观模式是一种结构型设计模式,它提供了一个统一的接口(外观)来访问复杂系统的子系统集合。通过外观模式,我们可以隐藏系统的复杂性,并提供一个简洁的接口供客户端使用 。
在软件开发过程中,我们经常会遇到这样的问题:如何在不修改原有代码的基础上,对某个功能进行扩展?这时,我们就需要使用一种设计模式来解决这个问题,我们要讨论的就是外观模式(Facade Pattern)。
外观模式是一种将一组接口转换为一个单独的类的方法,使得子系统中的各个组件可以更容易地使用这些接口,这种模式的主要目的是简化客户端与子系统之间的交互,提高系统的可扩展性和可维护性。
外观模式的主要角色有以下几个:
1、外观(Facade):外观是一个高层接口,它定义了一组方法,这些方法封装了子系统中的多个接口,客户端只需要与外观类进行交互,而不需要了解子系统中的具体实现。
2、子系统(Subsystem):子系统是实际实现外观所依赖的一组接口和数据结构,它负责处理具体的业务逻辑。
3、抽象组件(ConcreteComponent):抽象组件是子系统中的一个具体实现,它实现了外观所定义的接口,其他子系统可以通过继承抽象组件来实现自己的外观。
下面我们通过一个简单的例子来说明外观模式的使用,假设我们有一个在线购物系统,它包含以下几个组件:商品管理、订单管理和用户管理,我们希望在不修改原有代码的基础上,为这个系统添加一个“库存查询”的功能。
我们定义一个库存查询的外观类(InventoryFacade):
public interface InventoryFacade { int getProductCount(); // 获取商品数量 int getOrderCount(); // 获取订单数量 }
我们创建两个抽象组件(ConcreteComponent),分别表示商品管理和订单管理:
public abstract class ProductManager implements InventoryFacade { private ConcreteProduct concreteProduct; public ProductManager(ConcreteProduct concreteProduct) { this.concreteProduct = concreteProduct; } @Override public int getProductCount() { return concreteProduct.getProductCount(); } } public abstract class OrderManager implements InventoryFacade { private ConcreteOrder concreteOrder; public OrderManager(ConcreteOrder concreteOrder) { this.concreteOrder = concreteOrder; } @Override public int getOrderCount() { return concreteOrder.getOrderCount(); } }
我们需要为每个子系统创建一个实现类(ConcreteComponent):
public class ConcreteProduct extends ProductManager { public ConcreteProduct() { super(new ConcreteProductImpl()); // 这里假设我们已经实现了一个具体的商品管理器类 ConcreteProductImpl } } public class ConcreteOrder extends OrderManager { public ConcreteOrder() { super(new ConcreteOrderImpl()); // 这里假设我们已经实现了一个具体的订单管理器类 ConcreteOrderImpl } }
我们在外观类中调用子系统的相应方法:
public class InventoryFacadeImpl implements InventoryFacade { private ProductManager productManager; private OrderManager orderManager; public InventoryFacadeImpl(ProductManager productManager, OrderManager orderManager) { this.productManager = productManager; this.orderManager = orderManager; } @Override public int getProductCount() { return productManager.getProductCount(); } @Override public int getOrderCount() { return orderManager.getOrderCount(); } }
我们可以在客户端代码中直接使用库存查询功能,而无需关心子系统中的具体实现:
public class Client { public static void main(String[] args) { InventoryFacade inventoryFacade = new InventoryFacadeImpl(new ConcreteProduct(), new ConcreteOrder()); // 这里假设我们已经实例化了商品管理器和订单管理器对象 ConcreteProductImpl 和 ConcreteOrderImpl) System.out.println("商品数量:" + inventoryFacade.getProductCount()); // 直接输出商品数量,无需关心商品管理器的实现细节)