前言
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
一个复杂的过程需要高级的接口以及具体实现的实现类,对于调用者来说并不关心实现的细节,只关心结果调用和结果输出。可以拆分子系统,或则单独的类进行构造门面模式。
- 访问一系列复杂的子系统提供一个简单的入口
- 客户端程序与多个子系统存在很大的依赖性
- 在层次化系统中,可以使用外观模式定义系统中每一层的入口,层与层之间不产生直接关系,而是通过外观类建立联系,降低层之间的耦合度。
1.定义一个购物过程的接口
/**
* 定义一个购物处理过程
*/
public interface PurchurseProcess {
//挑选商品
void pickGoods(String goodName);
//添加购物车
void addCart(String goodName);
//选择快递方式
void chooseDelivMode(String delivName);
//支付
void pay();
}
接口实现类:
/**
* 购物过程的实现类
*/
public class PurchurseProcessImpl implements PurchurseProcess{
@Override
public void pickGoods(String goodName) {
System.out.println("挑选商品:"+goodName);
}
@Override
public void addCart(String goodName) {
System.out.println("将商品"+goodName+"添加购物车!");
}
@Override
public void chooseDelivMode(String delivName) {
System.out.println("选择快递方式"+delivName);
}
@Override
public void pay() {
System.out.println("进行支付....");
}
}
简单的过程,使用外观模式前,我们需要每个步骤都得调用一次。
/**
* 模拟一个购物下单的过程
*/
public class FacadeDemo {
public static void main(String[] args) {
PurchurseProcessImpl process = new PurchurseProcessImpl();
//1.挑选物品
process.pickGoods("联想电脑");
//2.添加购物车
process.addCart("联想电脑");
//3.选择快递方式
process.chooseDelivMode("京东快递");
//4.支付完成
process.pay();
}
}
如果每个步骤都这样,步骤比较繁琐。外观模式可以帮助解决这个问题。
2.外观模式进行改造
代码如下
门面类中进行引入购买的接口类,提供一个统一接口进行购物。
/**
* 定义门面
*/
public class PurchurseFacade {
private PurchurseProcess purchurseProcess = new PurchurseProcessImpl();
/**
* 一个方法实现四个步骤
* @param goodName 商品名字
* @param deliveryMode 快递方式
*/
public void purchurseGoods(String goodName,String deliveryMode) {
//1.挑选物品
purchurseProcess.pickGoods(goodName);
//2.添加购物车
purchurseProcess.addCart(goodName);
//3.选择快递方式
purchurseProcess.chooseDelivMode(deliveryMode);
//4.支付完成
purchurseProcess.pay();
}
}
这样我们调用就简单多了,调用代码如下:
public class Client {
public static void main(String[] args) {
PurchurseFacade purchurseFacade = new PurchurseFacade();
//购买过程
purchurseFacade.purchurseGoods("华为mate30","圆通快递");
}
}
3. 思考
如果添加步骤呢,选择支付方式,选择快递地址呢,我们还需要进行步骤拆分,但是对于调用者来说并不关心步骤,只关心结果。
支付方式:
/**
* 选择支付方式
*/
public class PayModeFacde {
/**
* 选择支付方式
* @param payMode
*/
public void selectPayMode(String payMode){
System.out.println("选择支付方式:"+payMode);
}
}
快递地址:
/**
* 增加选择邮件地址
*/
public class DeliveryAddress {
/**
* 选择邮寄地址
* @param address
*/
public void addAddress(String address){
System.out.println("选择邮寄地址:"+address);
}
}
原来的类进行改造,添加额外增加的功能步骤:
//增加选择地址 private DeliveryAddress deliveryAddress = new DeliveryAddress(); //选择支付方式 private PayModeFacde payModeFacde = new PayModeFacde();
/**
* 定义门面
*/
public class PurchurseFacade {
private PurchurseProcess purchurseProcess = new PurchurseProcessImpl();
//增加选择地址
private DeliveryAddress deliveryAddress = new DeliveryAddress();
//选择支付方式
private PayModeFacde payModeFacde = new PayModeFacde();
/**
* 一个方法实现四个步骤
* @param goodName 商品名字
* @param deliveryMode 快递方式
*/
public void purchurseGoods(String goodName,String deliveryMode) {
//1.挑选物品
purchurseProcess.pickGoods(goodName);
//2.添加购物车
purchurseProcess.addCart(goodName);
//添加快递地址
deliveryAddress.addAddress("xx省");
//3.选择快递方式
purchurseProcess.chooseDelivMode(deliveryMode);
//增加
payModeFacde.selectPayMode("支付宝");
//4.支付完成
purchurseProcess.pay();
}
}
输出结果:
挑选商品:华为mate30
将商品华为mate30添加购物车!
选择邮寄地址:xx省
选择快递方式圆通快递
选择支付方式:支付宝
进行支付....
Mybatis源码 Configuration结构分析
由上面的类图可以看出,client只需要调用Configuration的newMetaObject(Object object)
方法就可以得到一个MetaObject对象,而具体的对象是怎么生成与client无关,下面我们可以看一下Configuration的部分源码分析。
//Configuration 类:
public class Configuration {
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
//MetaObject类
public class MetaObject {
private Object originalObject;
private ObjectWrapper objectWrapper;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
private ReflectorFactory reflectorFactory;
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
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);
}
}
}
由上面的部分源码可以看出,客户端只需要调用Configuration的newMetaObject(Object object)方法,并传递一个Object参数,就可以获取对应的MetaObject,至于具体的产生什么样的MetaObject,则有MetaObject的类的forObject(object, objectFactory, objectWrapperFactory, reflectorFactory)方法实现。
源码解析(Tomcat ServletRequest)
使用tomcat作为web容器时,接收浏览器发送过来的请求,tomcat会将请求信息封装成ServletRequest对象,如下图①处对象。但是大家想想ServletRequest是一个接口,它还有一个子接口HttpServletRequest,而我们知道该request对象肯定是一个HttpServletRequest对象的子实现类对象,到底是哪个类的对象呢?可以通过输出request对象,我们就会发现是一个名为RequestFacade的类的对象。
RequestFacade类就使用了外观模式。先看结构图:
为什么在此处使用外观模式呢?
定义RequestFacade类,分别实现 ServletRequest ,同时定义私有成员变量 Request ,并且方法的实现调用 Request的实现。然后,将 RequestFacade上转为 ServletRequest 传给servlet 的 service方法,这样即使在 servlet 中被下转为RequestFacade ,也不能访问私有成员变量对象中的方法。既用了 Request ,又能防止其中方法被不合理的访问。
总结
可以看出外观模式并不符合开闭原则,需要修改原来的接口代码进行改造,比如日志输出 ,我们并不关心日志如何实现的,只需要引入日志相关的类。
————————————————
版权声明:本文为CSDN博主「小刘同学要加油呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37400096/article/details/126979857
相关文章: