设计模式学习笔记(39)——命令模式及其实现

本文通过烤肉串和鸡翅的烹饪实例,深入解析了命令模式在软件设计中的应用。介绍了从紧耦合到松耦合的设计转变,展示了如何使用命令模式解决实际问题,如批量处理请求、请求撤销和日志记录等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

命令模式
一、紧耦合设计
在这里插入图片描述

package operation;
class Barbecuer{

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

	public void BakeChickenWing() {
		System.out.println("烤鸡翅!");
	}
}
public  class Main{
	public static void main(String[] args){
		Barbecuer boy=new Barbecuer();
		boy.BakeMutton();
		boy.BakeMutton();
		boy.BakeMutton();
		boy.BakeChickenWing();
		boy.BakeMutton();
		boy.BakeMutton();
		boy.BakeChickenWing();
	}
}

二、松耦合设计
在这里插入图片描述

package operation;
abstract class Command{
	protected Barbecuer receiver;
	public Command(Barbecuer receiver) {
		this.receiver=receiver;
	}
	public abstract void ExcuteCommand();
}
class Barbecuer{
	
	public void BakeMutton() {
		System.out.println("烤羊肉串!");
	}
	public void BakeChickenWing() {
		System.out.println("烤鸡翅!");
	}
}
class BakeMuttonCommand extends Command{
	 
	public BakeMuttonCommand(Barbecuer receiver) {
		super(receiver);
		
	}
 
	
	public void ExcuteCommand() {
		
		receiver.BakeMutton();
	}
	
}
class BakeChickenWingCommand extends Command{
 
	public BakeChickenWingCommand(Barbecuer receiver) {
		super(receiver);
		
	}
 

	public void ExcuteCommand() {
	
		receiver.BakeChickenWing();
	}
}



class Waiter{
	private Command command;

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

	public void Notify() {
		command.ExcuteCommand();
	}
}
public  class Main{
	public static void main(String[] args){
	
		Barbecuer boy=new Barbecuer();
		Command bakeMuttonCommand1=new BakeMuttonCommand(boy);
		Command bakeMuttonCommand2=new BakeMuttonCommand(boy);
		Command bakeChikenWingCommand1=new BakeChickenWingCommand(boy);
		Waiter girl=new Waiter();
	
		girl.SetOrder(bakeMuttonCommand1);
		girl.Notify();
		girl.SetOrder(bakeMuttonCommand2);
		girl.Notify();
		girl.SetOrder(bakeChikenWingCommand1);
		girl.Notify();
	}
}

有几个问题:
1.真实的情况并不是用户点一个菜,服务员就通知厨房去做一个,应该是点完烧烤后服务员一次性通知。
2.如果此时鸡翅没了,不应该是客户来判断有没有,应该是服务员或烤肉串者来否决这个请求。
3.客户到底点了哪些烧烤或饮料,这是需要记录日志的,以备收费,也包括后期的统计。
4.客户完全有可能因为点的羊肉串太多而考虑取消一些还没有制作的肉串。
三、松耦合后

package operation;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
 
class Barbecuer{
	
	public void BakeMutton() {
		System.out.println("烤羊肉串!");
	}
	
	public void BakeChickenWing() {
		System.out.println("烤鸡翅!");
	}
}
abstract class Command{
	protected Barbecuer receiver;
	public Command(Barbecuer receiver) {
		this.receiver=receiver;
	}
	public abstract void ExcuteCommand();
}

class BakeMuttonCommand extends Command{
 
	public BakeMuttonCommand(Barbecuer receiver) {
		super(receiver);
		
	}
	public void ExcuteCommand() {
		
		receiver.BakeMutton();
	}
	
}
class BakeChickenWingCommand extends Command{
 
	public BakeChickenWingCommand(Barbecuer receiver) {
		super(receiver);
		
	}
 
	public void ExcuteCommand() {
	
		receiver.BakeChickenWing();
	}
}

class Waiter{
	private ArrayList<Command>orders=new ArrayList<Command>();
	public void SetOrder(Command command) {
		if(command.getClass().getName()=="fx.BakeChickenWingCommand") {
			System.out.println("服务员:鸡翅没有了。");
		}else {
			orders.add(command);
			SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			System.out.println("增加订单:"+command.getClass().getName()+"时间:"+df.format(new Date()));
		}
	}

	public void CancelOrder(Command command) {
		orders.remove(command);
		SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("取消订单:"+command.getClass().getName()+"时间:"+df.format(new Date()));
	}
	public void Notify() {
		Iterator<Command>cmd=orders.iterator();
		while(cmd.hasNext()) {
			cmd.next().ExcuteCommand();
		}
	}
}
 
public  class Main{
	public static void main(String[] args){
		
		Barbecuer boy=new Barbecuer();
		Command bakeMuttonCommand1=new BakeMuttonCommand(boy);
		Command bakeMuttonCommand2=new BakeMuttonCommand(boy);
		Command bakeChikenWingCommand1=new BakeChickenWingCommand(boy);
		Waiter girl=new Waiter();
		
		girl.SetOrder(bakeMuttonCommand1);
		girl.SetOrder(bakeMuttonCommand2);
		girl.SetOrder(bakeChikenWingCommand1);
		girl.CancelOrder(bakeMuttonCommand1);
		girl.Notify();
	}
}

运行结果:

增加订单:operation.BakeMuttonCommand时间:2020-06-22 13:08:46
增加订单:operation.BakeMuttonCommand时间:2020-06-22 13:08:46
增加订单:operation.BakeChickenWingCommand时间:2020-06-22 13:08:46 烤羊肉串!
烤羊肉串! 烤鸡翅!

四、命令模式
命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
在这里插入图片描述

package operation;

class Receiver{
	public void Action() {
		System.out.println("执行请求!");
	}
}
abstract class Command{
	protected Receiver receiver;
	public Command(Receiver receiver) {
		this.receiver=receiver;
	}
	abstract public void Excute();
}
class ConcreteCommand extends Command{
	public ConcreteCommand(Receiver receiver) {
		super(receiver);
	}
 
	
	public void Excute() {
	
		receiver.Action();
	}
}
class Invoker{
	private Command command;
 
	public void setCommand(Command command) {
		this.command = command;
	}
	public void ExecuteCommand() {
		command.Excute();
	}
}
public  class Main{
	public static void main(String[] args){
		Receiver r=new Receiver();
		Command c=new ConcreteCommand(r);
		Invoker i=new Invoker();
		i.setCommand(c);
		i.ExecuteCommand();
	}
}

五、命令模式作用
1.它能较容易地设计一个命令队列
2.在需要的情况下,可以较容易地将命令记入日志
3.允许接收请求的一方决定是否要否决请求
4.可以容易地实现对请求的撤销和重做
5.由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
最关键的优点就是命令模式把请求一个操作的对象与知道怎么执行的一个操作分割开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值