• 设计模式-模板模式


    模板模式一般适用于有一定的流程,而且在不同的业务场景中有着不同的流程实现的情况。发布流程涉及到编译,备份,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。

  • 相关阅读:
    狗 日 的 360
    Django搭建简单的站点
    ZOJ 3675 Trim the Nails(bfs)
    Qt移动应用开发(二):使用动画框架
    SPOJ QTREE2 lct
    [Phonegap+Sencha Touch] 移动开发77 Cordova Hot Code Push插件实现自己主动更新App的Web内容
    Bitmap工具类BitmapHelper
    Material-design icon生成插件
    闲聊ROOT权限——ROOT权限的前世今生
    Java深入浅出系列(四)——深入剖析动态代理--从静态代理到动态代理的演化
  • 原文地址:https://www.cnblogs.com/markytsai/p/13443245.html
Copyright © 2020-2023  润新知