命令模式将命令或者请求封装成一个对象,使用时,我们将命令传递给命令的调用者,命令的调用者对于命令如何执行一无所知,只需调用命令的方法来完成命令。命令锁操作的对象(命令接收者)与命令调用者完全分开。其结构图如下:
命令接口定义提供哪些命令,在具体的命令子类中,实现具体的命令操作,具体子类持有命令作用对象,也就是命令接收者的引用。用户类将命令接收者作为构造函数的参数传递给命令对象,创建命令对象这话将命令传递给命令的调用者。
例如,我们有一个按钮类Button,按钮可以支持多种不同的命令,如OnCommand定义打开命令,NextCommand定义下一集命令,MuteCommand定义静音命令,这些命令有调用者Button调用。而命令操作的对象可以是TV或者MP3。这时候可以使用命令模式来解耦TV、MP3和Button之间的关系。这个例子的UML图如下:
首先定义命令接收者(命令操作的对象)设备类Device及其子类,Device类定义设备支持的操作,供命令类调用(而不是供Button调用):
/**
* @author Brandon B. Lin
*
*/
public interface Device {
public abstract void on();
public abstract void next();
public abstract void mute();
}
/**
* @author Brandon B. Lin
*
*/
public class TV implements Device {
@Override
public void on() {
System.out.println("TV On");
}
@Override
public void next() {
System.out.println("TV Next");
}
@Override
public void mute() {
System.out.println("Mute TV");
}
}
/**
* @author Brandon B. Lin
*
*/
public class MP3 implements Device {
@Override
public void on() {
System.out.println("MP3 On");
}
@Override
public void next() {
System.out.println("MP3 Next");
}
@Override
public void mute() {
System.out.println("Mute MP3");
}
}
接着定义命令及其子类,命令作用在Device类上,调用设备的各种操作,命令类将命令及其作用对象绑定:
/**
* @author Brandon B. Lin
*
*/
public class OnCommand implements Command {
private Device deviceToTurnOn;
public OnCommand(Device deviceToTurnOn) {
this.deviceToTurnOn = deviceToTurnOn;
}
@Override
public void execute() {
deviceToTurnOn.on();
}
}
/**
* @author Brandon B. Lin
*
*/
public class NextCommand implements Command {
private Device deviceToNext;
public NextCommand(Device deviceToNext) {
this.deviceToNext = deviceToNext;
}
@Override
public void execute() {
deviceToNext.next();
}
}
/**
* @author Brandon B. Lin
*
*/
public class MuteAllCommand implements Command {
private List<Device> devicesToMute;
public MuteAllCommand(List<Device> devicesToMute) {
this.devicesToMute = devicesToMute;
}
@Override
public void execute() {
for (Device device : devicesToMute) {
device.mute();
}
}
}
定义完命令类之后,定义命令的调用者Button类,Button类不在乎命令执行什么,作用在谁身上,它只是简单地执行传递给它的命令。
/**
* @author Brandon B. Lin
*
*/
public class Button {
private Command commandWhenClicked;
public Button(String displayName, Command commandWhenClicked) {
this.commandWhenClicked = commandWhenClicked;
}
public void click() {
commandWhenClicked.execute();
}
}
最后来个测试类:
/**
* @author Brandon B. Lin
*
*/
public class CommandTest {
public static void main(String[] args) {
TV tv = new TV();
OnCommand onTVCommand = new OnCommand(tv);
new Button("OnTV", onTVCommand).click();
MP3 mp3 = new MP3();
NextCommand nextMP3Command = new NextCommand(mp3);
new Button("NextMP3", nextMP3Command).click();
List<Device> deviceToMute = new ArrayList<>();
deviceToMute.add(tv);
deviceToMute.add(mp3);
MuteAllCommand muteAllCommand = new MuteAllCommand(deviceToMute);
new Button("MuteAllButton", muteAllCommand).click();
}
}
我们可以看到,Button类在被按下的时候执行什么命令,如何执行,作用于哪些设备身上,都不是Button类关心的事,它只负责调用命令的execute方法执行命令。将这些命令逻辑从Button类中抽离出来,而Button类可以聚焦于Button外观等内容。这样,Button类与Device类实现解耦,如果想改变某个按钮操作的对象,无需对Button类进行更改,只需要传递一个不同的命令即可。同时,定义新的命令变得十分容易。
命令模式是回调函数Callback的面向对象版本,它可以实现撤销(undo)操作。
Java中,线程是命令模式的典型例子。Runnable接口相当于命令模式中的Command,而Thread相当于命令的调用者,只不过这个调用动作是Java自动完成,不需要我们手动编写代码,而在上面的例子中,我们需要调用Button类的click方法。线程不关心Runnable如何执行,操作哪些对象,它只简单执行Runnable中定义的run方法,然后把注意力放在线程本身的管理和控制上。这样一来,Thread和Runnable具体操作的对象实现解耦,很容易定义一个不同的命令(Runnable)而无需更改Thread类。
另外,javax.swing.Action也是命令模式的实现。
分享到:
相关推荐
设计模式之命令模式 设计模式之命令模式代码 设计模式之命令模式代码
命令模式(Command) 用意:把一个请求封装到一个对象中,把发出命令和执行命令的责任分开,委派给不同的对象实现。
设计模式之命令模式,你值得拥有,帮你快速掌握命令模式的实例。
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或纪录请求日志,以及支持可撤销的操作。 那么让我们简要的说一下命令模式的特点。 它能比较容易地设计一个...
设计模式这命令模式的Java实现版本和UML设计类图
学习js设计模式的例子,用到了命令模式、修装模式
命令模式代码demo 命令模式代码demo 命令模式代码demo
C#设计模式之 -- 命令模式代码示例和应用Dome
命令模式的示例代码和文档,学习命令模式的参考资料。
C#命令模式应用
命令模式(多命令)的代码(Java), 详细描述了命令模式(多命令)的代码架构.
ios平台中通过最简单的代码讲解命令模式,可在博客http://blog.sina.com.cn/s/blog_161d504630102wxis.html中查看简单解释
命令模式的C++实现
设计模式--命令模式java例子
设计模式C++学习之命令模式(Command)
C#命令模式模型,参考GOF 《设计模式》,模型代码。
命令模式:某个方法需要完成某一个行为,但这个行为的具体实现无法确定,必须等到执行该方法时才可以确定, * 这是一个命令模式的一个实例
命令模式,最简单的实现命令模式,没有对需求的负责理解,只针对模式本身。最纯粹的体现命令模式的特点
命令模式的示例代码及类图(用powerDesign画的),都是自己亲手写的,很简单,看不懂你来杀我! 注:oom文件需要手工用powerDesign打开,默认没有被PD关联。