设计模式之外观模式
先来看模拟一下女同胞们生育险报销的过程,如下:
–>准妈妈住院生孩子–>医院缴纳费用–>出院时办理相关证明手续
–>拿着相关证明材料到公司,由公司进行信息核实并上报
–>社保局将报销费用返还
以上就是大致的一个生育险的报销过程,下面我们通过代码来实现下:
public interface IFertilityExpenseProcess {
public abstract void pay();
public abstract void dealWithFormalities();
public abstract void application();
public abstract void transfer();
}
public class FertilityExpenseProcess implements IFertilityExpenseProcess {
@Override
public void pay(){
System.out.println("缴纳生孩子的相关费用....");
}
@Override
public void dealWithFormalities(){
System.out.println("出院办理生育险报销的相关证明材料...");
}
@Override
public void application(){
System.out.println("拿着相关材料到公司,由公司进行信息核实并上报....");
}
@Override
public void transfer(){
System.out.println("社保局审核通过后,将报销费用返还....");
}
}
public class Main {
public static void main(String[] args) {
IFertilityExpenseProcess process = new FertilityExpenseProcess();
System.out.println("准妈妈到医院生孩子...");
process.pay();
process.dealWithFormalities();
process.application();
process.transfer();
}
}
以上是一个简单的实现,在整个生育险报销流程中,顺序是不能随便改变的,且每个需要报销的妈妈(可怜的上班族)都要经历这样的流程,尤其是报销的流程太过繁琐,如果是一个对流程不熟悉的,那么可能会导致多次到医院补充相关的证明材料,此时是多么想有一种方式来自动处理这一繁琐的流程,下面来实现下:
public class ExpenseProcess {
IFertilityExpenseProcess iFertilityExpenseProcess = new FertilityExpenseProcess();
//封装处理过程
public void process(){
iFertilityExpenseProcess.pay();
iFertilityExpenseProcess.dealWithFormalities();
iFertilityExpenseProcess.application();
iFertilityExpenseProcess.transfer();
}
}
public class Main {
public static void main(String[] args) {
ExpenseProcess process = new ExpenseProcess();
System.out.println("准妈妈到医院生孩子...");
process.process();
}
}
整个时候我们对流程进行了封装,想要报销,只需要调用process()方法即可,妈妈们不用再关心具体的流程了。
这也是我们经常会用到的一种编码方式,当要实现一个复杂逻辑时,需要对复杂逻辑按职责进行细分成多个方法后,在将多个方法统一封装到一个对外的接口中,使得具体的逻辑对使用者是透明的,这也是门面模式的雏形。
门面模式官方的定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。
在看下面的代码:
public class ExpenseProcessFacade {
ExpenseProcess process = new ExpenseProcess();
//封装处理过程
public void process(){
process.process();
}
}
public class Main {
public static void main(String[] args) {
//门面模式
ExpenseProcessFacade process = new ExpenseProcessFacade();
System.out.println("准妈妈到医院生孩子...");
process.process();
}
}
这里为什么 要把**ExpenseProcess 放到ExpenseProcessFacade 中呢,对照以上的定义来看,ExpenseProcess 是属于子系统内部的,只不过它对生育险报销逻辑进行了一次封装而已,如果妈妈们有其他的需求,比如“产后恢复”等等,此时就不适合在往这个类里面添加更多的逻辑了。
那如果此时要添加其他的逻辑,应该怎么办呢,很简单,首先需要定义好相关的类和实现,以及逻辑封装类,然后在ExpenseProcessFacade **引用新添加的类,再对外提供一个新的接口,调用新的逻辑封装类的方法即可:
public class PostpartumRecovery {
public void find(){
System.out.println("寻找可以进行产后恢复的健身房...");
}
public void consulting(){
System.out.println("咨询课程费用");
}
public void pay(){
System.out.println("支付相关费用");
}
}
public class PostpartumRecoveryWrapper {
private PostpartumRecovery postpartumRecovery = new PostpartumRecovery();
public void process(){
postpartumRecovery.find();
postpartumRecovery.consulting();
postpartumRecovery.pay();
}
}
public class ExpenseProcessFacade {
private ExpenseProcess process = new ExpenseProcess();
private PostpartumRecoveryWrapper recovery = new PostpartumRecoveryWrapper();
//封装处理过程
public void process(){
process.process();
}
public void processRecovery(){
recovery.process();
}
}
public class Main {
public static void main(String[] args) {
//门面模式
ExpenseProcessFacade process = new ExpenseProcessFacade();
System.out.println("准妈妈到医院生孩子...");
process.process();
process.processRecovery();
}
}
以上这种写法,每新添加一个逻辑,只需要在**ExpenseProcessFacade **中添加封装了对应逻辑的类即可,这样即使以后有改动,也只需要修改对应类接口中的逻辑即可,并不会影响到用的调用。