外观设计模式
-
简单介绍
外观模式又称为门面设计模式,是一种结构型设计模式。该模式旨在通过某个类(门面类),聚合各个子系统,并对外提供一组易用的接口。接口的复杂业务,由门面类通过其聚合的子系统协作完成。对于上游调用者来说完全透明。
-
使用场景
客户程序的实现,依赖多个子系统共同提供的服务。此种场景可以引入门面模式,通过门面类来聚合不同的子系统,对外提供统一、易用的接口,供客户程序直接调用。
-
场景举例
MyBatis中,MetaObject对象的获取方式采用了门面设计模式。用户在获取该对象是,可以直接通过调用门面类Configuration来直接或获取。而不需要通过创建多个对象,再通过调用MetaObject的构造方法来获得。
-
门面设计模式UML类图
-
具体实现
-
描述
- 背景:开学期间,小明准备买台台式机,他了解到台式机可以自己购买零件组装,也可以委托商家帮忙组装,考虑到自己是电脑小白最终小明选择委托商家帮忙购买零件和组装电脑
- MemorySeller:内存条卖家,提供售卖内存条的途径,充当外面模式中的SubSystem子系统角色
- GraphicsCardSeller:显卡卖家,提供售卖显卡服务,充当外面模式中的SubSystem子系统角色
- HardDiskSeller:硬盘卖家,提供售卖硬盘服务,充当外面模式中的SubSystem子系统角色
- ComputerSellerFacade:电脑卖家,充当外面模式中的Facade角色,负责向各个配件卖家(子系统)购买电脑配件
- Computer:商家组装好的电脑
-
实现代码
ComputerSellerFacade.java
/** * 电脑卖家:充当外观模式中的Facade(门面)角色 * 负责向各个配件卖家(子系统)购买电脑配件 */ public class ComputerSellerFacade { /** * 聚合各个子系统 */ private MemorySeller memorySeller; private GraphicsCardSeller graphicsCardSeller; private HardDiskSeller hardDiskSeller; public ComputerSellerFacade(MemorySeller memorySeller, GraphicsCardSeller graphicsCardSeller, HardDiskSeller hardDiskSeller) { this.memorySeller = memorySeller; this.graphicsCardSeller = graphicsCardSeller; this.hardDiskSeller = hardDiskSeller; } public Computer getComputer() { return assembleComputer(); } /** * 通过各个子系统,购买并组装配件 * @return 电脑 */ private Computer assembleComputer() { String memory = memorySeller.getMemory(); String graphicsCard = graphicsCardSeller.getGraphicsCard(); String hardDisk = hardDiskSeller.getHardDisk(); return new Computer(memory, hardDisk, graphicsCard); } }
MemorySeller.java
/** * 内存条卖家:充当外观模式中的SubSystem(子系统)角色 * 提供售卖内存条服务 */ public class MemorySeller { /** * 获取内存条 * @return 一根 Kingston 32GB 内存条 */ public String getMemory() { return "Kingston 32GB"; } }
HardDiskSeller.java
/** * 硬盘卖家:充当外面模式中的SubSystem(子系统)角色 * 提供售卖硬盘服务 */ public class HardDiskSeller { /** * 获取硬盘 * @return 一块西部数据1T硬盘 */ public String getHardDisk() { return "WD 1T"; } }
GraphicsCardSeller.java
/** * 显卡卖家:充当外观模式中的SubSystem(子系统)角色 * 提供售卖显卡服务 */ public class GraphicsCardSeller { /** * 获取显卡 * @return 一块 RTX 2080Ti 的显卡 */ public String getGraphicsCard() { return "RTX 2080Ti"; } }
Computer.java
/** * 电脑,商家组装后的成品 */ public class Computer { /** * 电脑的相关配件 * 内存 */ private String memory; /** * 硬盘 */ private String hardDisk; /** * 显卡 */ private String graphicsCard; public Computer(String memory, String hardDisk, String graphicsCard) { this.memory = memory; this.hardDisk = hardDisk; this.graphicsCard = graphicsCard; } @Override public String toString() { return "Computer{" + "memory='" + memory + '\'' + ", hardDisk='" + hardDisk + '\'' + ", graphicsCard='" + graphicsCard + '\'' + '}'; } }
Client.java
/** * 客户端 * 小明,从电脑卖家ComputerSellerFacade手中获得电脑 */ public class Client { public static void main(String[] args) { ComputerSellerFacade seller = new ComputerSellerFacade(new MemorySeller(), new GraphicsCardSeller(), new HardDiskSeller()); // 只需要通过电脑卖家,便可直接获得电脑,而不需要自己去电脑配件商家中逐个购买 Computer computer = seller.getComputer(); // 查看购买到的电脑配置信息 System.out.println(computer); } }
-
-
源码展示
-
MyBatis中获取一个对象实例的 MetaObject 对象可以通过调用MetaObject 的构造方法直接获取,其获取方式源代码如下:
MetaObject.java
public class MetaObject { /** * 通过MetaObject的构造方法,来获取object对象的MetaObject对象实例 * 需要手动创建ObjectFactory、ObjectWrapperFactory等对象实例 * 创建过程十分繁琐 */ private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { this.originalObject = object; this.objectFactory = objectFactory; this.objectWrapperFactory = objectWrapperFactory; this.reflectorFactory = reflectorFactory; if (object instanceof ObjectWrapper) { this.objectWrapper = (ObjectWrapper)object; } else if (objectWrapperFactory.hasWrapperFor(object)) { this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object); } else if (object instanceof Map) { this.objectWrapper = new MapWrapper(this, (Map)object); } else if (object instanceof Collection) { this.objectWrapper = new CollectionWrapper(this, (Collection)object); } else { this.objectWrapper = new BeanWrapper(this, object); } } }
而MyBatis中通过引入Configuration(门面类角色),来聚合ObjectFactory、ObjectWrapperFactory等MetaObject构造方法所需要的参数对象,将创建MetaObject的逻辑封装在体内,对外提供了一个简单的获取方法:newMetaObject(),直接供客户端调用,具体源代码如下:
Configuration.java
/** * 相当于外观设计模式中的门面类角色 */ public class Configuration { /** * 聚合构造MetaObject的所需要用的各个类(子系统) */ protected ObjectFactory objectFactory; protected ObjectWrapperFactory objectWrapperFactory; protected ReflectorFactory reflectorFactory; /** * 构造方法,直接实例化MetaObject的所需要用的各个类(子系统) */ public Configuration() { this.reflectorFactory = new DefaultReflectorFactory(); this.objectFactory = new DefaultObjectFactory(); this.objectWrapperFactory = new DefaultObjectWrapperFactory(); } /** * 为客户端提供一个封装了复杂逻辑的简单方法,用户只需要传入object即可 */ public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, this.objectFactory, this.objectWrapperFactory, this.reflectorFactory); } }
-