设计模式(五)命令模式

参考:

  1. headfirst设计模式

你接到一个项目,做一个控制遥控器,可以控制家里所有电器,灯,冰箱,空调,热水器等等。遥控器的生产厂家已经和这些家居的厂商谈好了,他们提供了每个家居的控制方法,一个java的class,现在只有简单的开关功能。你要做的是在一个遥控器上可以控制所有家居。

嗯,现在你看到了一些基本的说明文档,各个家居的控制类:
在这里插入图片描述
要做这样的一个遥控器,你不会傻到使用if语句去判断每次按钮按下的是什么吧。

if(开灯){
    light.on();
}else if(开电视){
    tv.open();
}

万一有新的家居进来,你就要不停的修改这个方法,对开闭原则来说,真是够呛,而且维护起来很麻烦啊。

这个时候就可以使用命令模式,它可以将“动作的请求者”从“动作的执行者”对象中解耦。

怎么理解这句话呢?如果按照最开始的设计,动作请求者,遥控器的按钮,和对象的执行者light,tv,等都是在一起的(一个方法中被调用。在一起就说明是耦合)。你必须知道按下了那个按钮,然后找到对应的tv或者light,调用他们的方法。但是命令模式就是要解决这个,也就是将按钮和具体的执行light.on()方法分离。

具体怎么做
在这个设计中,采用“命令对象”就可以办到。利用命令对象,把请求封装成一个特定的对象,比如打开灯这个请求。新建一个对象,调用light的on方法,所以这个命令对象就要有这个light的引用。
那么当按下遥控器的开关时,我们只需要调用这个命令对象来做相应的工作就可以了。这样遥控器就和light解耦了。

来点代码
还记得oo设计的思想吗?是面向接口编程而不是面向实现编程。 接口或者abstract。
那么首先应该想到要有一个接口,怎么把这个接口找出来呢?

前面我们想到要有一个命令对象,使用命令对象去调用具体的家居,而遥控器只需要使用命令对象做相关的操作就可以了。为了解耦。

遥控器的每个按钮都是一个操作控制器controller,这个控制器一定是持有命令对象的引用,而命令对象持有具体的家居。所以他们才能够一级一级的调用。

既然遥控器不需要知道具体的命令对象是啥,那么这个引用就可以用接口代替了,所以命令对象都应该实现一个接口。

public interface Command {
    public void execute();
}

既然有了接口,就来实现以下某个具体的命令对象,比如灯具的开关对象。
先要有light,厂家就提供了开和关。

public class Light {
    public void on(){
        System.out.println("开灯");
    }
    public void off(){
        System.out.println("关灯");
    }
}

再来一个命令对象,持有电灯对象。调用她的开关。

public class LightCommand implements Command {
    Light light;
    public LightCommand(Light light) {
        this.light = light;
    }
    @Override
    public void execute() {
        light.on();
    }
}

然后来实现遥控器的按钮,持有接口,调用接口的方法,从而与具体的light解耦。

public class LightController  {
    Command command;
    public LightController(){}
    public void setCommand(Command command) {
        this.command = command;
    }
    public void button(){
        command.execute();
    }
}

测试:

    @Test
    public void test(){
        Light light = new Light();
        LightCommand command = new LightCommand(light);
        LightController controller = new LightController();
        controller.setCommand(command);
        controller.button();
        // 自己实现一个车库的方法吧。
        GarageDoor door = new GarageDoor();
        GarageDoorCommand command1 = new GarageDoorCommand(door);
        controller.setCommand(command1);
        controller.button();
    }
打印:
开灯
up

在测试中,只需要更换command,就可以实现对具体家居的控制了。

命令模式: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。命令模式是对功能方法的抽象,并不是对对象的抽象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值