白话设计模式_命令模式1

        先看例子:

//灯:有开、关两个操作
public class Light {
	public void off(){
		System.out.println("off...");
	}
	public void on(){
		System.out.println("on...");
	}
}
//命令
public interface Command {
	public void execute();
}
public class LightOnCommand implements Command {
	Light light;
	public LightOnCommand(Light light){
		this.light = light;
	}	
	public void execute() {
		light.on();
	}
}
public class LightOffCommand implements Command {
	Light light;
	public LightOffCommand(Light light){
		this.light = light;
	} 	
	public void execute() {
		light.off();
	}
}
//遥控器
public class RemoteControl {
	Command c;
	public void setCommand(Command c){
		this.c = c;
	}
	public void pressButton(){
		c.execute();
	}
}

       测试:

 

public class CommandLoader {
public static void main(String[] args) {
                //遥控器对象
               RemoteControl src = new RemoteControl();
               //灯对象
                Light light = new Light();
		LightOnCommand lo = new LightOnCommand(light);
		//LightOffCommand lo = new LightOffCommand(light);

		src.setCommand(lo);
		src.pressButton();
	}
}
 

        运行结果是:

on...

 

        我们分析下这段代码可知,程序的最终目的是通过“遥控器”控制“灯”打开,效果类似于在RemoteControl类的pressButton()方法里直接:

Light light = new Light();
light.on();

        这样很直接,也很好理解,但是灵活性不好,如果我们要换一种“灯”或者给“灯”添加一些新的操作,比如brighter()调高亮度、dim()调低亮度,就必须修改RemoteControl类了,根本原因在于上面RemoteControl类中使用了硬编码,我们把具体的类Light放进了RemoteControl类中,殊不知这个具体的东西以后可能常常有变化。

      再分析下,我们上面这种写法,让RemoteControl类针对抽象的Command接口,而将Light的具体操作封装进Command的实现类中,相当于在RemoteControl和Light中间人为的加了一层,RemoteControl针对Command编程,而一个具体的Command实际上就代表了原来Light里的一个操作。

      这就是命令模式:请一个请求封装成对象,从而可以使用不同的请求对客户进行参数化。

      下面是命令模式的类图模型:
       
        Invoker:命令的调用者,但却不直接与命令的实施者Receiver关联,而是关联一个Command引用;

      Command:(一般用接口)表示命令,给所有需要执行的实际操作一个统一的“接口”;

      ConcreteCommand: 具体的操作命令,实现Command接口,同时关联一个Receiver,表示作用在哪个实施者上面的操作;

      Receiver:命令的实施者,可将它的每一种操作都封装成一个独立的命令对象,比如LightOnCommand、LightOffCommand、LightXXXCommand等,它们都实现Command接口,从而有一个共同的身份Command;

      CommandLoader: 负责组装Reveiver和ConceteCommand,实际的客户端操作Invoker对象。

      仔细分析命令模式,可以看出它有很多好处:

1、请求的调用者与请求的实施者解耦

      Invoker(请求调用者)不用像以前一样知道每一Receiver(请求的实施者),假如我们要扩展Light,例如添加一个dim()方法调低亮度,RemoteControl完全不用修改,只用添加一个LightDimCommand命令,在把它动态组装到ConreteCommand中即可。

2、可实现撤销功能

      不使用命令模式时,light.on()就是一个原子操作,执行完了就完了,而命令模式中由于我们把这个操作封装进了一个对象中,而对象是一个实实在在的有状态的东西,我们可以把它保存起来,这样即使操作结束,由于我们之前保存了那个命令对象,我们也就知道它到底干了什么,当然也就可以撤销了。

      我们甚至可以多级撤销,只要将命令对象存放进一个stack栈中,之后便可以轻松取出来。


总结:

       命令模式的关键点在于:共同的接口Command、用Command对象封装每一个请求。另外,对象有状态、可以保存,以至于我们可以拿这些对象做一些扩展的功能。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值