Head First设计模式-命令模式

命令模式定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

初看到定义时觉得好抽象,“请求”是个什么。

“一个技术往往是伴一个问题的出现而出现的”,我们应该想,为什么会出现这个模式?这个模式究竟有什么好处?

书中首先提出的一个需求:“公司想要设计一个家电自动化遥控器的API,公司有一些厂商类(如电灯、电视),还有一个遥控器,遥控器有七个可编程的插槽(每个插槽都可以指定一个不同的家电装置),每个插槽都有对应的开关按钮,还有一个撤销按钮。”

拿到需求时就想 厂商类如果就七个,那好,我直接把命令写到按钮里 。可是厂商类不只是七个,有十几个甚至会上百个。如果写好几个遥控器,那还能叫智能遥控器吗?所以不能这么设计。再者面向对象思想也不提倡这样做。那怎么办呢?

书中用餐厅来引出命令模式,在餐厅中

  1. 顾客把订单写好交给服务员
  2. 服务员把订单交给厨师
  3. 厨师看到订单后做好大餐

这其中,服务员获悉顾客想要什么,通过订单告诉厨师做什么。
服务员只知道厨师会做餐,不管厨师怎么去做。

我们可以这样想,服务员知道厨师会做餐(服务员拿着订单通知厨师),服务员喊一声“订单来了”(服务员调用orderUp()),厨师听到喊声看到订单后准备做餐(根据接收的指令准备)。
不管是哪个服务员哪个厨师,服务员把订单给厨师后,厨师也知道做什么,厨师不管谁订的还是谁送来的。这样订单把顾客与厨师就隔离了。

这里我们把顾客当作“发出请求的对象”,把厨师当作“接收与执行请求的对象”,而订单不就是“包含了请求的一个对象”。

回到我们的需求中,此时我们是否可以将厂商类(灯、电视)当作厨师(接收与执行请求的对象),将遥控器当作订单(包含了请求的一个对象)
这里的“请求”就是我们的一个命令。

这里命令模式就出现了,我们要控制灯,就要写一个控制灯的命令。要控制电视,就要写一个控制电视的命令。所以命令中包含了一个“接收与执行请求对象”。然后我们要写很多命令,可是我们的遥控器中不可能要包含每个命令。所以这里我们要创建一个命令接口,这个接口中有一个执行的方法(execute()…),每个命令要实现这个接口,然后在执行方法中完成“接收者”要做的动作。

相关代码如下:
灯类(厂商类)

public class Light {

    public void off() {
        System.out.println("Light is off!");
    }

    public void on() {
        System.out.println("Light is on!");
    }

}

命令接口

/**
*命令接口
**/
public interface Command{
    public void execute();
}

实现命令接口的控制灯的命令

/**
*控制灯的命令(开灯)
**/
public class LightOnCommand implements Command{
    //命令中持有一个灯对象
    Light light;
    public LightOnCommand(Light light){
        this.light=light;
    }

    //实现接口中的execute()方法
    public void execute(){
        //开灯
        light.on();
    }
}

控制装置(遥控器)

public class SimpleRemoteControl{
    //包含命令
    Command command;
    public SimpleRemoteControl(){}

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

    //按钮方法,按下按钮时执行动作
    public void buttonWasPressed(){
        //调用命令的执行方法
        this.command.execute();
    }
}

测试顾客

public class RemoteControlTest{
    public static void main(String[] agrs){
        //实例化灯(接收者)
        Light light = new Light();
        //实例化开灯命令类(包含一个灯的对象)
        LightOnCommand lightOnCommand = new LightOnCommand (light);
        //实例化控制装置(遥控器)
        SimpleRemoteControl simpleRemoteControl = new SimpleRemoteControl();

        //将开灯命令装入控制装置
        simpleRemoteControl.setCommand(lightOnCommand );
        //执行方法(开灯)
        simpleRemoteControl.buttonWasPressed();
    }
}

输出结果:
Light is on!

到此,命令模式已经实现原型了。遥控器只能控制七个装置,用命令模式我们就能很方便的更换装置了,而不用更改遥控器。

这其实就遵循了据说的设计原则:对扩展开放,对修改关闭。针对接口编程不要针对实现编程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值