设计模式-模板模式
模板模式一般适用于有一定的流程,而且在不同的业务场景中有着不同的流程实现的情况。发布流程涉及到编译,备份,SQL执行,部署。这种情况下模板模式是一个不错的选择。
模板模式有时可以和组合模式一块使用,可以更能体现出Java面向接口编程的特性。
首先定义三个接口,分别代表流程中的不同的业务步骤
public interface StepOne { void doStepOne(); } public interface StepTwo { void doStepTwo(); } public interface StepThree { void doStepThree(); }
合并这些接口,用一个接口来代表所有接口,避免后面会有大量的冗余接口代码
public interface FullStep extends StepOne, StepTwo, StepThree { }
接下来是定义模板,这里我会先定义一个规范模板的接口
public interface Process { void process(); // Process nextProcess(); }
具体 模板实现
public abstract class ProcessImpl implements Process { private StepOne stepOne; private StepTwo stepTwo; private StepThree stepThree; @Override public void process() { if (stepOne != null) { stepOne.doStepOne(); } if (stepTwo != null) { stepTwo.doStepTwo(); } if (stepThree != null) { stepThree.doStepThree(); } if (nextProcess() != null) { nextProcess().process(); } } abstract Process nextProcess(); }
在抽象类ProcessImpl中,需要注入流程接口声明,这里我定义了三步,这里的
private StepOne stepOne;
private StepTwo stepTwo;
private StepThree stepThree;
怎么注入进去呢,由于这三个接口会被后面每一个具体的实现类实现,那么注入就是这些实现类共同要做的事情,所以可以把注入放在它们的公共父类来实现。所以我们需要一个公共父类
public abstract class FullProcess extends ProcessImpl implements FullStep { public void init() { setStepOne(this); setStepTwo(this); setStepThree(this); } }
通过调用init方法便可以实现注入实现类对象到模板类的字段当中,这里还差一点,需要把这个类的调用自动化,那么需要用到spring的扩展接口。
public class OrderProcess extends FullProcess implements FullStep { @PostConstruct public void initialize() { super.init(); } @Override Process nextProcess() { return null; } @Override public void doStepOne() { } @Override public void doStepThree() { } @Override public void doStepTwo() { } }
这里我才用的是@PostConstruct注解,当然也可以采用实现InitializingBean接口,重写afterPropertiesSet()方法来实现。
OrderProcess公共实现创建完成后,便可以实现我们每一种流程对应的接口了,这里我实现了两个模板实现类。
public class ApProcess extends OrderProcess { @Override public void doStepOne() { System.out.println("AP step 1"); } @Override public void doStepThree() { System.out.println("AP step 3"); } @Override public void doStepTwo() { System.out.println("AP step 2"); } }
public class CenterProcess extends OrderProcess { @Override public void doStepOne() { System.out.println("Center step 1"); } @Override public void doStepThree() { System.out.println("Center step 3"); } @Override public void doStepTwo() { System.out.println("Center step 2"); } }
下面测试下
@SpringBootTest @RunWith(SpringRunner.class) public class ProcessTeset { @Autowired private ApplicationContext applicationContext; @Test public void test() { for (ProcessEnum value : ProcessEnum.values()) { Process process = (Process) applicationContext.getBean(value.getType()); process.process(); } } }
测试结果
在这整个流程中,使用了模板模式和组合模式,具体的逻辑下沉的子类中实现。但是由于模板中的流程被拆分成了各个接口,所以需要把子类的实现注入到模板的属性中去,这样不仅可以规范模板的流程,还分离了流程中的每一个节点,比较方便。如果后期需要加节点,那么只需要加一个接口即可;如果需要修改节点逻辑,只需要修改接口签名或者修改实现类即可。总之可以做到流程的动态化。
详细的代码传到了GitHub上https://github.com/markytsai/design-demos。