命令模式将命令或者请求封装成一个对象,使用时,我们将命令传递给命令的调用者,命令的调用者对于命令如何执行一无所知,只需调用命令的方法来完成命令。命令锁操作的对象(命令接收者)与命令调用者完全分开。其结构图如下:
命令接口定义提供哪些命令,在具体的命令子类中,实现具体的命令操作,具体子类持有命令作用对象,也就是命令接收者的引用。用户类将命令接收者作为构造函数的参数传递给命令对象,创建命令对象这话将命令传递给命令的调用者。
例如,我们有一个按钮类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也是命令模式的实现。
分享到:
相关推荐
命令模式是一种行为设计模式,它的主要目的是将请求者与接收者解耦,使得请求的发起者无需知道哪个对象会执行这个请求,同时也让系统更容易扩展。这种模式在软件工程中广泛应用,特别是在事件驱动和分布式系统中。 ...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式广泛应用在各种场景中,以提高代码的灵活...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在iOS开发中,命令模式尤其适用于处理事件驱动的编程场景,因为...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式常用于解耦发出命令的对象和执行命令的...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在C#编程中,命令模式常用于实现解耦发送者和接收者,提高代码的...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求以便支持可撤消的操作。在这个简单的计算器例子中,我们将探讨如何使用命令模式来实现加法、...
在“记事本 使用了策略模式和命令模式”这个主题中,我们将深入探讨这两种设计模式以及它们如何应用于记事本软件的实现。 首先,让我们了解策略模式。策略模式是一种行为设计模式,它允许在运行时选择算法或策略。...
命令模式是一种行为设计模式,它将请求封装为一个对象,使得可以使用不同的请求、队列或者日志请求,也可以支持可撤销的操作。在C++中,命令模式的应用可以帮助我们更好地组织代码,提高代码的可扩展性和可维护性。...
命令模式是一种行为设计模式,它将请求封装为一个对象,使得你可以参数化不同的请求,对请求排队或记录请求日志,以及支持可撤销的操作。C#作为.NET框架的主要编程语言,非常适合应用这种模式。本篇文章将深入探讨...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中实现命令模式,我们可以按照以下步骤进行: 1. **定义...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在C#编程中,命令模式常用于实现解耦,使得调用者与执行者之间...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中,命令模式的应用非常广泛,尤其在需要解耦调用者和接收...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在本示例中,我们将深入探讨命令模式的核心概念和实现方式。 ...
命令模式是一种设计模式,它将请求封装为一个对象,从而使我们能使用不同的请求、队列或者日志请求,以及支持可撤销的操作。在本代码demo中,我们将深入探讨这一模式的实现及其应用。 命令模式的核心思想是解耦调用...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在本文中,我们将深入探讨命令模式的原理、结构和实际应用,并...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中,命令模式的应用非常广泛,尤其在需要解耦调用者和执行...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java编程中,命令模式的应用广泛且实用。 命令模式的核心是将...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在C++中,我们可以利用面向对象的特性来有效地实现这个模式。 ...
命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中实现命令模式,我们可以创建一个接口或者抽象类作为命令...