zoukankan      html  css  js  c++  java
  • 行为类型11-7:命令模式(Command Pattern)

    1. 概述

    将一个请求以命令的形式包裹在对象中,从而使你可用不同的请求对客户进行参数化,然后传给调用对象;对请求排队或记录请求日志,以及支持可撤消的操作。。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

    2. 介绍

    2.1 意图

    将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

    2.2 主要解决

    在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

    2.3 何时使用

    在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

    2.4 如何解决

    通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。

    2.5 关键代码

    定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

    2.6 应用实例

    struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。

    2.7 优点

    1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。

    2.8 缺点

    使用命令模式可能会导致某些系统有过多的具体命令类。

    2.9 使用场景

    1.抽象出待执行的动作以参数化某对象。

    2.在不同的时刻指定、排列和执行请求。

    3.支持取消操作。

    4.支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。

    5.用构建在原语操作上的高层操作构造一个系统。

    认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

    2.10 注意事项

    系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。

    3. 参与者

    1.Command
    	声明执行操作的接口。
    
    2.ConcreteCommand
    	将一个接收者对象绑定于一个动作。
    	调用接收者相应的操作,以实现Execute。
    
    3.Client
    	创建一个具体命令对象并设定它的接收者。
    
    4.Invoker
    	要求该命令执行这个请求。
    
    5.Receiver
    	知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
    

    4. 类图

    在这里插入图片描述

    5. 例子

    5.1 Command

    public abstract class Command {
        
        protected Receiver receiver;
        
        public Command(Receiver receiver) {
            this.receiver = receiver;
        }
        
        public abstract void execute();
    }
    

    5.2 ConcreteCommand

    public class CommandImpl extends Command {
    
        public CommandImpl(Receiver receiver) {
            super(receiver);
        }
        
        public void execute() {
            receiver.request();
        }
    }
    

    5.3 Invoker

    public class Invoker {
    
        private Command command;
        
        public void setCommand(Command command) {
            this.command = command;
        }
        
        public void execute() {
            command.execute();
        }
    }
    

    5.4 Receiver

    public class Receiver {
        public void receive() {
            System.out.println("This is Receive class!");
        }
    }
    

    Test

    public class Test {
    
        public static void main(String[] args) {
            Receiver rec = new Receiver();
            Command cmd = new CommandImpl(rec);
            Invoker i = new Invoker();
            i.setCommand(cmd);
            i.execute();
        }
    }
    

    result

    This is Receive class!
    

    6 示例2

    我们首先创建作为命令的接口 Order,然后创建作为请求的 Stock 类。实体命令类 BuyStockSellStock,实现了 Order 接口,将执行实际的命令处理。创建作为调用对象的类 Broker,它接受订单并能下订单。

    Broker 对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令。CommandPatternDemo,我们的演示类使用 Broker 类来演示命令模式。
    在这里插入图片描述

    6.1 command

    import com.sun.tools.corba.se.idl.constExpr.Or;
    
    public interface Order {
        void execute();
    }
    
    class BuyStock implements Order{
        private Stock abcStock;
    
        public BuyStock(Stock abcStock) {
            this.abcStock = abcStock;
        }
    
        @Override
        public void execute() {
            abcStock.buy();
        }
    }
    
    class SellStock implements Order {
        private Stock abcStock;
    
        public SellStock(Stock abcStock) {
            this.abcStock = abcStock;
        }
    
        @Override
        public void execute() {
            abcStock.sell();
        }
    }
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Broker {
        private List<Order> orderList = new ArrayList<Order>();
    
        public void takeOrder(Order order){
            orderList.add(order);
        }
    
        public void placeOrders(){
            for(Order order : orderList){
                order.execute();
            }
            orderList.clear();
        }
    }
    
    
    public class Stock {
        private String name = "ABC";
        private int quantity = 10;
    
        public void buy(){
            System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] bought");
        }
        
        public void sell(){
            System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] sold");
        }
    }
    
    
    public class CommandPatternDemo {
        public static void main(String[] args) {
            Stock abcStock = new Stock();
    
            BuyStock buyStockOrder = new BuyStock(abcStock);
            SellStock sellStockOrder = new SellStock(abcStock);
    
            Broker broker = new Broker();
            broker.takeOrder(buyStockOrder);
            broker.takeOrder(sellStockOrder);
    
            broker.placeOrders();
        }
    }
    
    Stock [ Name: ABC, Quantity: 10 ] bought
    Stock [ Name: ABC, Quantity: 10 ] sold
    
  • 相关阅读:
    怎样为flash配置Alcon调试工具
    8.9Go简介
    8.14GO之条件语句
    8.10Go之基础语法
    8.11Java之数组知识回顾
    8.13Go之常量
    8.10Go执行流、编译、特点、转义字符
    8.14Go之运算符(Operator)
    8.14Java之使用HttpClient类通过POST方式上传文件
    8.10Go之语言数据类型
  • 原文地址:https://www.cnblogs.com/daozhangblog/p/12446357.html
Copyright © 2011-2022 走看看