命令模式
一、定义
命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
(命令模式是一种对象行为型模式,其别名为动作模式或事务模式.)
命令模式的本质是:对命令进行封装,将发出命令的责任与执行命令的责任分割开。
二、特点
优点:
- 类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用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();
}
}
【运行截图】
喜欢的话记得点赞收藏哟😊
Java设计模式—博文专栏持续更新!