行为型模式—命令模式

一、定义

命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
(命令模式是一种对象行为型模式,其别名为动作模式或事务模式.)

命令模式的本质是:对命令进行封装,将发出命令的责任与执行命令的责任分割开。

二、特点

优点:

  • 类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command 抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
  • 可扩展性:Command的子类可以非常容易地扩展,增加新的命令很方便。
  • 可以比较容易设计一个命令队列和宏命令,并方便地实现对请求的撤销和恢复
  • 命令模式结合其他模式:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题等

缺点:

  • 可能会导致某些系统有过多的具体命令类。如:有N个命令,Command的子类就不是几个,而是N个,这点需要在项目中考虑使用。

模式扩展:
宏命令又称为组合命令,它是命令模式和组合模式联用的产物。
宏命令也是一个具体命令,不过它包含了对其他命令对象的引用,在调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法,一个宏命令的对象成员可以是简单命令,还可以继续是宏命令。执行一个宏命令将执行多个具体命令,从而实现对命令的批处理。

三、使用场景

以下情况可以使用职责链模式:

  • 需要将请求调用者与请求接收者解耦,使得调用者和接收者不直接交互
  • 需要在不同时间指定请求、请求排队和执行请求。
  • 需要支持命令的撤销操作和恢复操作
  • 需要将一组操作组合在一起,即支持宏命令。

四、类图

在这里插入图片描述

角色:
Command:抽象命令类
ConcreteCommand: 具体命令类
Invoker:调用者
Receiver:接受者
Client:客户类

五、实战代码

将水果订单封装成命令对象并调用执行

【Command.java】

package command;

public interface Command {
    void execute();    //声明一个执行方法

}

【OrderCommand .java】

package command;

public class OrderCommand implements Command {
    private Operator receiver;
    private Order order;
    //放两个参数,一个是执行者,一个是执行的目标
    public OrderCommand(Operator receiver,Order order){
        this.receiver =receiver;
        this.order=order;
    }
    
    public void execute() {
        // TODO Auto-generated method stub
        System.out.println(order.getId()+" 号顾客的成品");
        receiver.MarkFuit(order);
    }

}

【Order.java】

package command;

import java.util.HashMap;

public class Order {

    private int id;
    private HashMap<String,Integer> fruitmap;
    public Order(){
        fruitmap=new HashMap<String,Integer> ();
        
    }
    public int getId() {
        // TODO Auto-generated method stub
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public HashMap<String,Integer> getFruitmap() {
        return fruitmap;
    }
    public void setFruitmap(String fruitkind,int quantity) {
        this.fruitmap.put(fruitkind, quantity);
    }

}

【Waitor_Invoker.java】

package command;

import java.util.ArrayList;

public class Waitor_Invoker {
    private ArrayList<Command> commands=null;
    public Waitor_Invoker(){
        commands=new ArrayList<Command>();
        
    }
    public void setCommand(Command cmd){
        commands.add(cmd);
    }
    public void OrderUp(){
        System.out.println("有订单");
        for(Command cmd:commands){
            if(cmd!=null)
                cmd.execute();
        }
    }
}

【Operator.java】

package command;

public class Operator {

    public void MarkFuit(Order order) {
        // TODO Auto-generated method stub
        String str="";
        for(String key:order.getFruitmap().keySet()){
            str+=key+order.getFruitmap().get(key);
        }
        System.out.println("黑暗混合汁:"+str);
    }

}

【ClientClass.java】

package command;

public class ClientClass {

    public static void main(String[] args) {
        //创建多个订单
        Order order1=new Order();
        order1.setId(1);
        order1.setFruitmap("橙子", 1);
        order1.setFruitmap("梨子", 2);
        order1.setFruitmap("苹果", 3);

        Order order2=new Order();
        order2.setId(2);
        order2.setFruitmap("香蕉", 4);
        order2.setFruitmap("葡萄", 2);
        order2.setFruitmap("西红柿", 3);
        //创建操作者
        Operator op=new Operator();
        //将多个订单封装成命令对象
        OrderCommand cmd1=new OrderCommand(op,order1);
        OrderCommand cmd2=new OrderCommand(op,order2);

        //创建调用者并加命令进去
        Waitor_Invoker waitor=new Waitor_Invoker();
        waitor.setCommand(cmd1);
        waitor.setCommand(cmd2);

        //执行命令
        waitor.OrderUp();
    }

}

运行截图:

在这里插入图片描述

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容