外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
一个复杂的过程需要高级的接口以及具体实现的实现类,对于调用者来说并不关心实现的细节,只关心结果调用和结果输出。可以拆分子系统,或则单独的类进行构造门面模式。
模拟一个购物的过程,进行挑选物品,添加购物车,选择快递方式,支付等。
代码如下:
/**
* 定义一个购物处理过程
*/
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();
}
}
如果每个步骤都这样,步骤比较繁琐。外观模式可以帮助解决这个问题。
代码如下
门面类中进行引入购买的接口类,提供一个统一接口进行购物。
/**
* 定义门面
*/
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","圆通快递");
}
}
如果添加步骤呢,选择支付方式,选择快递地址呢,我们还需要进行步骤拆分,但是对于调用者来说并不关心步骤,只关心结果。
支付方式:
/**
* 选择支付方式
*/
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省
选择快递方式圆通快递
选择支付方式:支付宝
进行支付....
可以看出外观模式并不符合开闭原则,需要修改原来的接口代码进行改造,比如日志输出 ,我们并不关心日志如何实现的,只需要引入日志相关的类。