设计模式学习笔记——命令模式

命令模式

命令模式,将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。(行为类模式)

结构图


代码实现

抽象命令类Command
/**
 * 声明命令,对外公布
 *
 * @author xukai 2016年3月30日 下午11:27:18
 * 
 */
public abstract class Command {

	public abstract void execute();

}

调用者Invoker
/**
 * 调用者,调用命令
 *
 * @author xukai 2016年3月30日 下午11:28:04
 * 
 */
public class Invoker {

	private Command command;

	public void setCommand(Command command) {
		this.command = command;
	}

	public void action() {
		command.execute();
	}

}

接受者Receiver
/**
 * 接受者,负责接受命令和执行命令
 *
 * @author xukai 2016年3月30日 下午11:29:07
 * 
 */
public class Receiver {

	public void doSomething() {
		System.out.println("接受者-业务逻辑处理");
	}

}

命令类:ConcreteCommand
/**
 * 具体命令的实现
 *
 * @author xukai 2016年3月30日 下午11:33:40
 * 
 */
public class ConcreteCommand extends Command {

	private Receiver receiver;

	public ConcreteCommand(Receiver receiver) {
		super();
		this.receiver = receiver;
	}

	@Override
	public void execute() {
		receiver.doSomething();
	}

}

客户端调用:
public class Client {

	public static void main(String[] args) {
		Receiver receiver = new Receiver();

		Command command = new ConcreteCommand(receiver);

		// 直接执行命令
		command.execute();

		// 通过调用者执行命令
		Invoker invoker = new Invoker();
		invoker.setCommand(command);

		invoker.action();
	}

}
输出:
接受者-业务逻辑处理
接受者-业务逻辑处理

demo

问题:烧烤店点菜。

结构图


代码实现

抽象命令Command
/**
 * 抽象命令
 *
 * @author xukai 2016年3月30日 下午11:53:19
 * 
 */
public abstract class Command {

	protected Barbecuer barbecuer;

	public Command(Barbecuer barbecuer) {
		super();
		this.barbecuer = barbecuer;
	}

	public abstract void excutedCommand();
}

具体命令
/**
 * 烤羊肉串命令
 *
 * @author xukai 2016年3月30日 下午11:57:01
 * 
 */
public class BakeMuttonCommand extends Command {

	public BakeMuttonCommand(Barbecuer barbecuer) {
		super(barbecuer);
	}

	@Override
	public void excutedCommand() {
		barbecuer.bakeMutton();
	}

}

/**
 * 烤鸡翅命令
 *
 * @author xukai 2016年3月30日 下午11:58:04
 * 
 */
public class BakeChickenWingCommand extends Command {

	public BakeChickenWingCommand(Barbecuer barbecuer) {
		super(barbecuer);
	}

	@Override
	public void excutedCommand() {
		barbecuer.bakeChickenWing();
	}

}

烤肉者:
/**
 * 做烧烤的人:请求的的处理者
 *
 * @author xukai 2016年3月30日 下午11:54:38
 * 
 */
public class Barbecuer {

	public void bakeMutton() {
		System.out.println("烤羊肉串");
	}

	public void bakeChickenWing() {
		System.out.println("烤鸡翅");
	}

}

服务员:
/**
 * 服务员:请求接受者
 *
 * @author xukai 2016年3月30日 下午11:58:36
 * 
 */
public class Waiter {

	private List<Command> orders = new ArrayList<>();

	public void setOrder(Command command) {
		orders.add(command);
		System.out.println("增加订单:" + command.toString() + ",时间: " + (new Date()));
	}

	public void cancle(Command command) {
		orders.remove(command);
		System.out.println("取消订单:" + command.toString() + ",时间 :" + (new Date()));
	}

	public void resolve() {
		for (Command command : orders) {
			command.excutedCommand();
		}
	}

}
客户端:
public class Client {

	public static void main(String[] args) {
		// 开店准备
		// 烧烤师
		Barbecuer barbecuer = new Barbecuer();
		// 提供命令
		Command bakeMuttonCommand1 = new BakeMuttonCommand(barbecuer);
		Command bakeMuttonCommand2 = new BakeMuttonCommand(barbecuer);
		Command bakeChickenWingCommand1 = new BakeChickenWingCommand(barbecuer);
		
		Waiter waiter = new Waiter();
		// 服务员添加菜单
		waiter.setOrder(bakeMuttonCommand1);
		waiter.setOrder(bakeMuttonCommand2);
		waiter.setOrder(bakeChickenWingCommand1);
		// 菜单交给烧烤师
		waiter.resolve();
		// 客人该主意了,不要鸡翅了
		waiter.cancle(bakeChickenWingCommand1);
		// 菜单交给烧烤师
		waiter.resolve();
	}
	
}
客户端输出:
增加订单:com.xk.day0330.command.demo.BakeMuttonCommand@41a7d9e7,时间: Thu Mar 31 00:14:16 CST 2016
增加订单:com.xk.day0330.command.demo.BakeMuttonCommand@360088ee,时间: Thu Mar 31 00:14:18 CST 2016
增加订单:com.xk.day0330.command.demo.BakeChickenWingCommand@5d1ddcf4,时间: Thu Mar 31 00:14:18 CST 2016
烤羊肉串
烤羊肉串
烤鸡翅
取消订单:com.xk.day0330.command.demo.BakeChickenWingCommand@5d1ddcf4,时间 :Thu Mar 31 00:14:18 CST 2016
烤羊肉串
烤羊肉串
把吃烧烤分成了三步:客户点菜,服务员记录菜单,烧烤师做烧烤,实现了松耦合。

总结

优点(封装性好,扩展性好)

1.容易形成命令队列;
2.命令可以写入日志;
3.允许接受请求的一方决定是否要否决请求(如:烤肉卖完了);
4.可以实现撤销和重做;
5.各个具体命令类相互之间不影响;

缺点

命令假如过多,那么每一个命令都需要一个命令类封装,哪怕只是很简单的命令或者几行代码的事。

核心:把请求一个操作的对象与知道怎么执行一个操作的对象分割开。

敏捷开发原则

不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般不要着急去实现它,事实上,在需要的时候通过重构实现并不困难,只有在真正需要撤销、恢复等功能时,重构原来代码为命令模式才有意义。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值