设计模式之命令模式(一)

在本次学习过程中,我们把封装带到一个全新的境界:把方法调用(method invocation)封装起来。没错,通过封装方法调用,我们可以把运算块包装成形。

所以调用此运算的对象不需要关心事情是如何进行的,只要知道如何使用包装成形的方法来完成它就可以。通过封装方法调用,也可以做一些很聪明的事情,例如记录日志,或者重复使用这些封装来实现撤销。让我们开始吧

现在有一个用户A,他们家有很多家电,在装修的时候,他让装修公司把这些家电当成了一个整体,想要通过一个遥控器就能控制家里的电灯、风扇、热水器、音响设备和其他的类似的可控制装置,这样的话就显得很高大上。

所以呢,他让每个厂商投提供了一组Java类,用来控制家电。手上又有一个遥控器,希望我们能够创建一组控制遥控器的API,让每个插槽都能控制一个或一组装置,即通过一个遥控器就能控制所有家电,是不是很酷。

我们先来看下厂商给的类。

这个类确实不少呀,而且接口也各有差异。还有更麻烦的,随着家电数量的增加,这样的类还会越来越多。那么,如何设计一个遥控器API就变得很有挑战性了是吧。

所以,命令模式应运而生了。在我们的设计中,采用“命令模式”,利用命令对象,把请求(例如打开电灯)封装成一个特定对象(例如客厅电灯对象)。所以,如果对每个按钮都存储一个命令对象,那么当按钮被按下的时候,就可以请命令对象做相关的工作。遥控器并不需要知道工作内容是什么,只要有个命令对象能和正确的对象沟通,把事情做好就可以了。这样,遥控器和电灯对象都解耦了。

可能把遥控器换成餐厅点餐,大家会更容易理解。我在这里简单描述下:首先顾客到了餐厅,根据菜单点了一部分菜,把菜单给服务员;服务员拿到了订单,就提交到柜台上,并向后厨喊了一声“xx号桌xx订单”来了;后厨根据菜单进行配菜,烧菜。全称服务员都不需要知道订单具体内容是什么,只要将桌上的客户点的餐提供给后厨即可,这和我们的遥控器就是一个道理了。

第一个命令对象

实现命令接口

那我们就来创建我们的命令对象吧。首先,我们得让所有的命令对象实现相同的包含一个方法的接口。在餐厅订餐的例子上,就是创建订单,我们在程序的世界里,取名叫做execute()

public interface Command {
    public void execute();
}
实现一个打开电灯的命令

现在,假设想实现一个打开电灯的命令。根据之前看到的厂商提供的类,Light类有两个方法,on和off。

// 这是一个命令,所以需要实现Command接口
public class LightOnCommand implements Command {
Light light;

// 构造器传入某个电灯,以便让这个命令控制,然后记录在实例变量中
public LightOnCommand(Light light) {
this.light = light;
}

// 这个execute方法调用接收对象的on方法
public void execute() {
light.on();
}

}

使用命令对象

现在,我们让遥控器工作起来,先来点简单的。假设遥控器只有一个按钮和对应的插槽,可以控制一个装置:

public class SimpleRemoteControl {
// 有一个插槽持有命令,而这个命令控制着一个装置
Command slot;

public SimpleRemoteControl() {}

// 这个方法用来设置插槽控制的命令
public void setCommand(Command command) {
slot = command;
}

// 当按下按钮时,这个方法就会被调用,使得当前命令衔接插槽,并调用它的execute方法
public void buttonWasPressed() {
slot.execute();
}
}

就这样我们就能实现一个简单的遥控器了。请看我们的测试

public class RemoteControlTest {
public static void main(String[] args) {
// 遥控器就是调用者,会传入一个命令对象,可以用来发出请求
SimpleRemoteControl remote = new SimpleRemoteControl();
// 现在创建一个电灯对象,此对象也就是请求的接收者
Light light = new Light();
    // 这里创建一个命令,然后将接收者传给它
LightOnCommand lightOn = new LightOnCommand(light);

// 把命令传给调用者
remote.setCommand(lightOn);
// 模拟按下按钮
remote.buttonWasPressed();
    }

}

定义命令模式

经过订餐流程的理解,以及刚才这个小练习,相信你也对命令模式内的类 和对象如何互动理解得很清楚了吧。那我们在这里趁热打铁,定义一下命令模式。

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

仔细想想,我们知道有一个命令对象通过在特定接收者上绑定一组动作来封装一个请求。要达到这一点,命令对象将动作和接收者包进对象中。这个对象只暴露出一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。从外面来看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道如果调用execute()方法,请求的目的就能达到。

让我们来看下命令模式的类图:

好了,通过这个简单的小练习,我们知道如何控制电灯的开关了。在前面厂商给的类中,还有好多方法,比如电风扇、吊灯、电视机、音响等等。控制单个我们已经能搞定了,那控制多个呢?是不是同理呢?还是你有更好的方式呢?小编想请你先动动你的小手,我们下次见分晓。

爱生活,爱学习,爱感悟,爱挨踢

(0)

相关推荐

  • 简说设计模式——命令模式

    一.什么是命令模式 在说命令模式前我们先来说一个小例子.很多人都有吃夜市的经历,对于那些推小车的摊位,通常只有老板一个人,既负责制作也负责收钱,我要两串烤串多放辣,旁边的人要了三串烤面筋不要辣,过了一 ...

  • 图解Java设计模式之命令模式

    智能生活项目需求 命令模式基本介绍 命令模式的原理类图 命令模式在Spring框架中JdbcTemplate应用源码分析 命令模式的注意事项和细节 智能生活项目需求 看一个具体的需求 我们买类一套智能 ...

  • Java设计模式【命令模式】

    命令模式 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互解耦,任何一方都不 ...

  • PHP设计模式之命令模式

    PHP设计模式之命令模式 命令模式,也称为动作或者事务模式,很多教材会用饭馆来举例.作为顾客的我们是命令的下达者,服务员是这个命令的接收者,菜单是这个实际的命令,而厨师是这个命令的执行者.那么,这个模 ...

  • [PHP小课堂]PHP设计模式之命令模式

    [PHP小课堂]PHP设计模式之命令模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 设计模式之命令模式

    让我们从一个简单的项目(遥控器)了解命令模式,然后再给出他的定义: 此项目地址: https://github.com/Stray-Kite/Design-Pattern/tree/master/sr ...

  • 设计模式之命令模式(三)

    我回来啦!今天是周六,一看命令模式还有一个总结未完成,赶紧爬起来做做好. 就如上一篇所说的,如果拥有了一个遥控器,却无法光凭按下一个按你,就同时能弄暗灯光.打开音响和电视.设置到DVD,并让热水器开始 ...

  • 设计模式之命令模式(二)

    上一次留给大家去做的实践,不知道大家执行的怎么样了呢. 我们通过一个简单的练习,完成了一个控制开关.那现在,我们打算将遥控器的每个插槽,对应到一个命令这样就要遥控器变成"调用者". ...

  • java设计模式-命令模式(Command)

    定义命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或者交易(Transaction)模式.命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化, ...

  • 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)