命令模式

本文介绍命令模式,以请舍友拿外卖为例,阐述其代码逻辑。命令模式让请求者和实现者解耦,方便对命令控制,如对多个命令进行日志记录等。还说明了其适用场景,包括发送者和执行者生命周期不同等,分析了优缺点,并得出相关结论。

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

情景

我想请舍友帮忙,帮我拿外卖上来。这个例子中,我即是命令的请求者Invoker,接收者自然就是舍友啦,roommateReceiver。命令即是让舍友帮忙拿外卖,命令可以有很多种,如买饮料啊,拿快递啊。所以通常设定为抽象类Command,具体的命令由其实现类实现。它的实现类要持有舍友的引用,这样才能让舍友帮忙拿外卖,舍友是具体实施操作,如拿外卖的具体对象。而“我”则持有命令的引用,只管对命令抽象类发出请求。

代码逻辑简单

以下凡是类或者方法中有字母“A”的地方,即代表拿外卖

package com.zlfan.command;

public class Invoker {
	
	private Command command;
	
	public Invoker(Command command){
		this.command = command;
	}
	
	public void requestA(){
		command.executeA();
	}
	
}
package com.zlfan.command;

public interface Command {
	
	void executeA();

}

拿外卖命令(抽象类Command的实现类) 

package com.zlfan.command;

public class ACommand implements Command {

	RoommateReceiver receiver;
	
	public ACommand(RoommateReceiver receiver){
		this.receiver = receiver;
	}
	
	@Override
	public void executeA() {
		receiver.A();
	}

}
package com.zlfan.command;

public class RoommateReceiver {
	
	public void A(){
		System.out.println("RoommateReceiver外卖帮忙拿到了");
	}
}

客户端测试类:

package com.zlfan.command;

public class Client {
	
	public static void main(String[] args) {
		RoommateReceiver roommate = new RoommateReceiver();
		Command command = new ACommand(roommate);
		
		Invoker me = new Invoker(command);
		me.requestA();
	}
	
}

输出:

RoommateReceiver外卖帮忙拿到了

整个流程就是 我——命令抽象类——命令的真正的执行者(舍友)。

做到这里,可能有同学会提出了,干嘛写的这么复杂,直接创建舍友类RoommateReceiver,调用就是了。

的确是可以这样做,但是命令模式的初衷是让命令请求者和命令实现者解耦,方便对命令进行各种控制。

(以下内容,参考自这里

打个比方:现在我们要对ConcreteCommandA与ConcreteCommandB以及其他一系列命令进行日志记录,并且两个命令之间的操作间隔不能大于1秒。

这种情况下要直接用两个类就会有大量的业务逻辑要在客户端进行处理,当命令增加,对每个命令的控制增加时,就会在Client里面产生大量的变化点,这样耦合就出来了,但是采用命令模式之后,对着一系列的命令我们都可以进行控制,这就是对变化点的封装。

实际Invoker代码如下:

public class Invoker
    {
        private ICommand lastCommand = null;
        private DateTime lastDateTime = DateTime.Now;

        public void RunCommand(ICommand command)
        {
            //记录操作日志
            Console.WriteLine(command.GetType().Name);
            //大于1秒,执行命令
            if (lastCommand == null || (DateTime.Now - this.lastDateTime).TotalSeconds > 1)
            {
                lastCommand = command;
                lastDateTime = DateTime.Now;
                command.Execute();
            }
            //小于1秒时不执行,并进行相应处理
            Console.WriteLine("操作间隔过短!");
        }
    }

适用场景

1. 命令的发送者和命令执行者有不同的生命周期。命令发送了并不是立即执行。

2. 命令需要进行各种管理逻辑。

3. 需要支持撤消/重做操作(这种状况的代码大家可以上网搜索下,有很多,这里不进行详细解读)。

优缺点

优:

  • 降低耦合度。
  • 新增一个命令/一组命令简单。
  • 调用同一方法实现不同功能。

缺:会产生过多具体命令类。

结论

 通过对上面的分析我们可以知道如下几点:

1. 命令模式是通过命令发送者和命令执行者的解耦来完成对命令的具体控制的。

2. 命令模式是对功能方法的抽象,并不是对对象的抽象。

3. 命令模式是将功能提升到对象来操作,以便对多个功能进行一系列的处理以及封装。

还可以通过组合模式结合在一起,将多个命令封装为一个“复合命令”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值