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
  • 相关阅读:
    摄像机
    变换
    纹理
    从顶点数据中传入顶点位置和顶点颜色
    使用glew和glad 新建窗口
    openGL坐标系
    glViewport函数用法
    彻底搞懂CSS文本、空白换行问题
    Django 搭建
    HessianSharp如何部署到IIS7上?
  • 原文地址:https://www.cnblogs.com/tanoak/p/11911859.html
Copyright © 2011-2022 走看看