美文网首页编程笔记
命令和职责链模式的快速实现 commons chain

命令和职责链模式的快速实现 commons chain

作者: 老瓦在霸都 | 来源:发表于2019-03-08 15:59 被阅读1次

    commons chain 是命令与职责链模式的经典实现 commons chain

    基本概念

    它有如下概念:

    • Context
    • Command
    • Chain
    • Filter
    • Catalog

    1) Context 上下文

    Context 表示一个应用程序的状态, 它其实是一个 java.util.map 的标记接口, 上下文是类似一个信封, 包含了完成一个事务所需的属性, 换句话说, 上下文是一个包含成员属性值的有状态对象

    2) Command 命令

    一个命令代表一个工作单元, 它只有一个入口方法

    public boolean execute(Context context)

    命令对通过上下文对象传递给它的状态进行操作,但不保留它自己的状态。命令可以组装成一个链,这样就可以从离散的工作单元创建复杂的事务。如果命令返回true,则不应执行链中的其他命令。如果一个命令返回false,那么链中的其他命令(如果有的话)可能会执行。

    3) Chain 职责链

    chain实现了命令接口,因此chain可以与命令互换使用。应用程序不需要知道它是在调用链还是命令,所以您可以从一个重构到另一个。chain 可以根据需要套入其他链条。这一性质被称为Liskov替换原理。

    4) Filter 过滤器

    理想情况下,每个command 都是独立的。可在现实生活中,我们有时需要分配资源,并确保不管发生什么,资源都会被释放. Filter 过滤器是一种特殊的命令, 它增加了一个后处理方法 postProcess 。在命令返回之前,职责链 Chain 会调用其中任何 Filter 的 postProcess 方法。一个实现了 Filter 的命令可以通过 postProcess 方法安全地释放它分配的任何资源,即使这些资源是与其他命令共享的

    5) Catalog 目录

    许多应用程序使用“facades”和“factories”以及其他技术来避免将层与层耦合在一起。层与层之间需要交互,但通常我们不希望它们在类名级别交互。目录是一组命令或链的逻辑上的名称,客户端可以在不知道命令的类名的情况下执行这些命令。

    举例如下

    package com.cisco.yafan.demo;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.chain.Command;
    import org.apache.commons.chain.Context;
    
    import org.apache.commons.chain.impl.ChainBase;
    import org.apache.commons.chain.impl.ContextBase;
    import org.junit.Test;
    
    import static junit.framework.TestCase.assertTrue;
    import static org.junit.Assert.assertFalse;
    
    @Slf4j
    class IvrCommand implements Command {
    
        private String name;
    
        public IvrCommand(String name) {
            this.name = name;
        }
    
        @Override
        public boolean execute(Context context) throws Exception {
            log.info("execute: {} for {}", name, context.get("phoneNumber"));
            if("please input your password".equals(name)) {
                if("pass".equals(context.get("password"))) {
                    context.put("balance", 10000);
                } else {
                    log.info("your password is incorrect.");
                    return true;
                }
    
    
            }
    
            return false;
        }
    }
    
    class IvrFlow extends ChainBase {
    
        public IvrFlow() {
    
            addCommand(new IvrCommand("welcome"));
    
            addCommand(new IvrCommand("please input account number"));
    
            addCommand(new IvrCommand("please input your password"));
    
            addCommand(new IvrCommand("your account balance is 10000"));
    
            addCommand(new IvrCommand("goodbye"));
    
        }
    }
    
    @Slf4j
    public class CommonsChainTest {
        @Test
        public void testIvrFlowCorrectPassword() throws Exception {
            Context context = new ContextBase();
            context.put("phoneNumber" , "86-123456789");
            context.put("password" , "pass");
    
            IvrFlow ivrFlow = new IvrFlow();
            ivrFlow.execute(context);
            assertTrue(Integer.valueOf("10000").equals(context.get("balance")));
        }
        @Test
        public void testIvrFlowIncorrectPassword() throws Exception {
            Context context = new ContextBase();
            context.put("phoneNumber" , "86-123456789");
            context.put("password" , "abcd");
    
            IvrFlow ivrFlow = new IvrFlow();
            ivrFlow.execute(context);
            assertFalse(Integer.valueOf("10000").equals(context.get("balance")));
        }
    }
    
    

    结果输出如下

    #testIvrFlowCorrectPassword
    execute: welcome for 86-123456789
    execute: please input account number for 86-123456789
    execute: please input your password for 86-123456789
    execute: your account balance is 10000 for 86-123456789
    execute: goodbye for 86-123456789
    
    #testIvrFlowIncorrectPassword
    execute: welcome for 86-123456789
    execute: please input account number for 86-123456789
    execute: please input your password for 86-123456789
    your password is incorrect.
    
    

    相关文章

      网友评论

        本文标题:命令和职责链模式的快速实现 commons chain

        本文链接:https://www.haomeiwen.com/subject/kqvwuqtx.html