zoukankan      html  css  js  c++  java
  • 命令模式

    • 概述
    • UML类图
    • 代码栗子
    • Spring源码体现
    • 总结

    概述

    • 概述
      命令模式使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。

    • 作用

      1. 类关系解耦,命令发送者与接受者解耦,命令行为参数化
    1. 可扩展性提高

    UML类图

    image.png

    代码栗子

    • 命令角色
    public abstract class AbstractCommand {
    
        /**
         * 将任务接受者交给子类
         */
        protected AbstractReceiver receiver ;
    
        public AbstractReceiver getReceiver() {
            return receiver;
        }
    
        public void setReceiver(AbstractReceiver receiver) {
            this.receiver = receiver;
        }
    
        public AbstractCommand(AbstractReceiver receiver) {
            this.receiver = receiver;
        }
    
        /**
         * 执行命令
         */
        public abstract void execute() ;
    
    }
    
    public class CoderCommand extends AbstractCommand {
    
        @Override
        public AbstractReceiver getReceiver() {
            return super.getReceiver();
        }
    
        @Override
        public void setReceiver(AbstractReceiver receiver) {
            super.setReceiver(receiver);
        }
    
    
        public CoderCommand(AbstractReceiver receiver) {
            super(receiver);
        }
        public CoderCommand() {
            super(new TestReceiver());
        }
    
        @Override
        public void execute() {
            super.receiver.doSomething();
        }
    }
    
    public class TestCommand extends  AbstractCommand{
        @Override
        public AbstractReceiver getReceiver() {
            return super.getReceiver();
        }
    
        @Override
        public void setReceiver(AbstractReceiver receiver) {
            super.setReceiver(receiver);
        }
    
        public TestCommand(AbstractReceiver receiver) {
            super(receiver);
        }
        public TestCommand() {
            super(new TestReceiver());
        }
    
        @Override
        public void execute() {
            super.receiver.doSomething();
        }
    }
    
    • 命令接受者
    public abstract class AbstractReceiver {
    
        /**
         * 抽象接收者,定义每个接收者都必须完成的业务
         */
        public abstract void doSomething();
    }
    
    public class CoderReceiver extends AbstractReceiver{
    
        /**
         * 抽象接收者,定义每个接收者都必须完成的业务
         */
        @Override
        public void doSomething(){
            System.out.println("修改了一行bug");
        }
    }
    
    public class TestReceiver extends AbstractReceiver{
    
        /**
         * 抽象接收者,定义每个接收者都必须完成的业务
         */
        @Override
        public void doSomething(){
            System.out.println("处理了一个bug测试");
        }
    }
    
    • 命令调用者
    public class Caller {
        private AbstractReceiver receiver;
    
        /**
         * 客户发出命令
         * @param receiver receiver
         */
        public void setCommand(AbstractReceiver receiver) {
            this.receiver = receiver;
        }
    
        //执行客户的命令
        public void action() {
            this.receiver.doSomething();
        }
    }
    
    • client
    public class Main {
        public static void main(String[] args) {
            Caller zhangSan = new Caller() ;
            System.out.println("客户张三");
            AbstractReceiver coderReceiver =new CoderReceiver() ;
            System.out.println("需要执行修改代码操作,找到了代码执行者,指派给他");
            zhangSan.setCommand(coderReceiver);
            zhangSan.action();
        }
    }
    
    • 运行效果

    image.png

    Spring源码体现

    熟记以下三种角色,一起来看下Spring是如何使用命令模式的

    • 命令调用角色 => org.springframework.jdbc.core.JdbcTemplate#query(String s, ResultSetExtractor) ;
    • 命令角色 =>org.springframework.jdbc.core.StatementCallback#doInStatement(Statement smt);
    • 命令接受角色 =>org.springframework.jdbc.core.JdbcTemplate#execute(StatementCallback);

    使用IDEA 双击shift查找类,进入org.springframework.jdbc.core.JdbcTemplate,找到query() 方法,找到query(final String sql, final ResultSetExtractor rse)。

    源码如下:

    @Override
    @Nullable
    public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
    // 省略非核心代码...
            /**
             * Callback to execute the query.
             */
            class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
                @Override
                @Nullable
                public T doInStatement(Statement stmt) throws SQLException {
                    ResultSet rs = null;
                    try {
                        rs = stmt.executeQuery(sql);
                        return rse.extractData(rs);
                    }
                    finally {
                        JdbcUtils.closeResultSet(rs);
                    }
                }
                @Override
                public String getSql() {
                    return sql;
                }
            }
          //命令调用者
            return execute(new QueryStatementCallback());
        }
    
    

    在代码的QueryStatementCallback类中可以看到它实现了StatementCallback接口,这个接口只有一个方法 doInStatement(Statement stmt)。将命令参数化如图:

    img

    根据传递的命令不同,执行execute()。

    源码如下:

    @Override
        @Nullable
        public <T> T execute(StatementCallback<T> action) throws DataAccessException {
            // 省略非关键代码 。。。
            Connection con = DataSourceUtils.getConnection(obtainDataSource());
            Statement stmt = null;
            try {
                stmt = con.createStatement();
                applyStatementSettings(stmt);
                T result = action.doInStatement(stmt);
                handleWarnings(stmt);
                return result;
            }
            catch (SQLException ex) {
                // Release Connection early, to avoid potential connection pool deadlock
                // in the case when the exception translator hasn't been initialized yet.
                String sql = getSql(action);
                JdbcUtils.closeStatement(stmt);
                stmt = null;
                DataSourceUtils.releaseConnection(con, getDataSource());
            
            }
            finally {
                JdbcUtils.closeStatement(stmt);
                DataSourceUtils.releaseConnection(con, getDataSource());
            }
        }
    
    

    总结

    • 命令模式牢记一点,行为发起者与行为执行者解耦
      栗子 老师布置作业为了提高效率,会让学习委员去收作业本,同学们只需要把作业交给学习委员就行了。这里面的行为发起者与行为执行者是谁呢?思考ing
  • 相关阅读:
    LeetCode "Super Ugly Number" !
    LeetCode "Count of Smaller Number After Self"
    LeetCode "Binary Tree Vertical Order"
    LeetCode "Sparse Matrix Multiplication"
    LeetCode "Minimum Height Tree" !!
    HackerRank "The Indian Job"
    HackerRank "Poisonous Plants"
    HackerRank "Kundu and Tree" !!
    LeetCode "Best Time to Buy and Sell Stock with Cooldown" !
    HackerRank "AND xor OR"
  • 原文地址:https://www.cnblogs.com/tanoak/p/11911859.html
Copyright © 2011-2022 走看看