23种设计模式之命令模式

23种设计模式之命令模式

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

命令模式是将某个产品的相关操作抽象成命令,由命令连接调用者和实现者,使命令的调用者与命令的实现者分离。

特点

  • 命令模式是一种行为型模式

通用类图

在这里插入图片描述

命令模式包含以下主要角色:

  • Command

    抽象命令角色

    声明所有执行的命令,拥有执行命令的抽象方法 execute()。

  • ConcreteCommand

    具体命令角色

    是抽象命令类的具体实现类,组合接收者对象,并通过调用接收者的功能来完成命令要执行的操作。

  • Receiver

    抽象接收者角色

    定义接收者公共的方法

  • ConcreteReceiver

    具体接收者角色

    完成执行命令功能的相关操作,是具体命令对象业务的真正实现者。

  • Invoker

    调用者角色

    接收命令,并执行命令,它聚合命令对象,并通过访问命令对象来执行相关请求。

优点

  • 类间解耦

    降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦(即调用者角色与接收者角色之间没有任何依赖关系)。

  • 可扩展性

    增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类(调用者Invoker和高层次的模块Client),它满足“开闭原则”,对扩展比较灵活。

  • 宏命令

    命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。

  • 命令模式结合其他模式会更优秀

    方便实现 Undo 和 Redo 操作。命令模式可以与备忘录模式结合,实现命令的撤销与恢复。

    命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。

缺点

  • 可能产生大量具体命令类。如果有N个命令,机会产生N个命令类。因为对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

应用场景

  • 当系统需要将请求调用者与请求接收者解耦时,命令模式使得调用者和接收者不直接交互。
  • 当系统需要随机请求命令或经常增加或删除命令时,命令模式比较方便实现这些功能。
  • 当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。
  • 当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现。

二、命令模式

需求:

假设有一个计算器界面,计算器上四个按键,分别是+、-、*、\,并且可以进行整型和浮点型数字的计算,使用命令模式实现该计算器。

抽象命令类(Command):

package command;

public abstract class Command {
	//  定义一个子类的全局共享变量
	protected final Receiver receiver;

	//  实现类必须定义一个接收者
	public Command(Receiver receiver) {
		this.receiver = receiver;
	}

	//  每个命令类都必须有一个执行命令操作的方法
	public abstract void execute();
}

具体命令类(ConcreteCommand):

package command;

public class AddCommand extends Command {

	//  声明自己的默认接收者
	public AddCommand() {
		super(new CalculateIntegerReceiver());
	}

	// 设置新的接收者
	public AddCommand(Receiver receiver) {
		super(receiver);
	}

	//  每个具体的命令都必须实现一个命令操作
	@Override
	public void execute() {
		//  业务处理
		receiver.add();
	}
}

package command;

public class SubCommand extends Command {

	//  声明自己的默认接收者
	public SubCommand() {
		super(new CalculateIntegerReceiver());
	}

	// 设置新的接收者
	public SubCommand(Receiver receiver) {
		super(receiver);
	}

	//  每个具体的命令都必须实现一个命令操作
	@Override
	public void execute() {
		//  业务处理
		receiver.sub();
	}
}

package command;

public class MultiCommand extends Command {


	//  声明自己的默认接收者
	public MultiCommand() {
		super(new CalculateIntegerReceiver());
	}

	// 设置新的接收者
	public MultiCommand(Receiver receiver) {
		super(receiver);
	}

	//  每个具体的命令都必须实现一个命令操作
	@Override
	public void execute() {
		//  业务处理
		receiver.multi();
	}
}

package command;

public class DivCommand extends Command {

	//  声明自己的默认接收者
	public DivCommand() {
		super(new CalculateIntegerReceiver());
	}

	// 设置新的接收者
	public DivCommand(Receiver receiver) {
		super(receiver);
	}

	//  每个具体的命令都必须实现一个命令操作
	@Override
	public void execute() {
		//  业务处理
		receiver.div();
	}
}

抽象接收者类(Receiver):

package command;

public interface Receiver {
   //  定义每个接收者都必须完成的业务
  
   public void add();

   public void sub();

   public void multi();

   public void div();
}

具体接收者类(ConcreteReceiver):

package command;

public class CalculateFloatReceiver implements Receiver {
	@Override
	public void add() {
		System.out.println("执行浮点数加法功能");
	}

	@Override
	public void sub() {
		System.out.println("执行浮点数减法功能");
	}

	@Override
	public void multi() {
		System.out.println("执行浮点数乘法功能");
	}

	@Override
	public void div() {
		System.out.println("执行浮点数除法功能");
	}
}

package command;

public class CalculateIntegerReceiver implements Receiver {
   @Override
   public void add() {
      System.out.println("执行整型加法功能");
   }

   @Override
   public void sub() {
      System.out.println("执行整型减法功能");
   }

   @Override
   public void multi() {
      System.out.println("执行整型乘法功能");
   }

   @Override
   public void div() {
      System.out.println("执行整型除法功能");
   }
}

调用者类(Invoker):

package command;

public class Invoker {
	//  命令
	private Command command;

	//  客户端发起命令
	public Invoker(Command command) {
		this.command = command;
	}

	//  设置命令
	public void setCommand(Command command) {
		this.command = command;
	}

	//  执行命令
	public void operate() {
		System.out.println("调用者执行命令command...");
		command.execute();
	}
}

Client:

package command;

public class Client {

	public static void main(String[] args) {
		// 默认使用 CalculateIntegerReceiver()进行命令处理
		Command commandAdd = new AddCommand();
		Command commandDiv = new DivCommand();

		// 设置使用 CalculateFloatReceiver()进行命令处理
		Command commandSub = new SubCommand(new CalculateFloatReceiver());
		Command commandMulti = new MultiCommand(new CalculateFloatReceiver());

		// 声明调用者Invoker
		Invoker invoker = new Invoker(commandAdd);
		// 执行命令
		invoker.operate();
		//  把命令交给调用者去执行
		invoker.setCommand(commandSub);
		// 执行命令
		invoker.operate();

		/**
		 * 输出结果:
		 * 调用者执行命令command...
		 * 执行整型加法功能
		 * 调用者执行命令command...
		 * 执行浮点数减法功能
		 */
	}
}

三、总结

命令模式将调用者和实现者进行解耦,减少高层模块(Client类)对低层模块(Receiver类)的依赖关系,提高系统整体的稳定性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值