命令设计模式是一种广为人知的设计模式,它属于行为设计模式(“四人帮”的一部分)。 顾名思义,它与应用程序中的动作和事件有关。
问题陈述:
假设有一个网页将在其中包含多个菜单的情况。 编写此代码的一种方法是使条件成立,并在每次单击菜单时执行操作。
private void getAction(String action){
if(action.equalsIgnoreCase('New')){
//Create new file
}
else if(action.equalsIgnoreCase('Open')){
//Open existing file
}
if(action.equalsIgnoreCase('Print')){
//Print the file
}
if(action.equalsIgnoreCase('Exit')){
//get out of the application
}
}
我们必须根据操作字符串执行操作。 但是,以上代码如果条件太多,则无法扩展。
意图:
- 动作的请求者需要与执行该动作的对象分离。
- 允许将请求封装为对象。 注意这一行,因为这对于命令模式是非常重要的概念。
- 允许将请求存储在队列中,即允许您存储稍后可以执行的操作列表。
解:
为了解决上述问题,这里可以使用命令模式。 如上所述,命令模式通过封装将上述动作移至对象。 这些对象在执行时将执行命令。 在这里,每个命令都是一个对象。 因此,我们将必须为每个菜单操作(例如NewClass , OpenClass , PrintClass , ExitClass)创建单独的类。 所有这些类都继承自父接口(即Command接口)。 此接口(命令接口)抽象/包装所有子动作类。
现在,我们介绍一个Invoker类,其主要工作是将操作与具有该操作的类进行映射。 它基本上保留了该动作,并通过调用execute()方法获得执行请求的命令。 糟糕! 我们在这里错过了另一个利益相关者。 这是Receiver类。 接收器类具有执行操作的知识。 接收者具有执行动作时该做什么的知识。
结构体:
以下是“命令设计”模式的参与者:
- 命令–这是用于执行操作的界面。
- ConcreteCommand –此类扩展了Command接口并实现了execute方法。 此类在操作和接收者之间创建绑定。
- 客户端–此类创建ConcreteCommand类并将其与接收者相关联。
- 调用程序–此类要求命令执行请求。
- 接收器–此类知道要执行的操作。
范例 :
- 使用诸如execute()之类的方法签名定义Command接口。 在上面的示例中, ActionListenerCommand是具有单个execute()方法的命令界面。
- 创建一个或多个派生类,这些派生类封装以下内容的一些子集:“接收者”对象,要调用的方法,要传递的参数。 在上面的示例中, ActionOpen和ActionSave是Concrete命令类,它们在接收者和操作之间创建绑定。 ActionOpen类在execute()内调用接收方(在本例中为Document类)类的action方法。 因此,命令接收器类需要做什么。
- 为每个延迟的执行请求实例化Command对象。
- 将Command对象从创建者传递到调用者。
- 调用者决定何时执行()。
- 客户端实例化Receiver对象(Document)和Command对象,并允许调用者调用命令。
代码示例:
命令界面:
public interface ActionListenerCommand {
public void execute();
}
接收器类别:
public class Document {
public void Open(){
System.out.println('Document Opened');
}
public void Save(){
System.out.println('Document Saved');
}
}
具体命令:
public class ActionOpen implements ActionListenerCommand {
private Document adoc;
public ActionOpen(Document doc) {
this.adoc = doc;
}
@Override
public void execute() {
adoc.Open();
}
}
祈求者等级:
public class MenuOptions {
private ActionListenerCommand openCommand;
private ActionListenerCommand saveCommand;
public MenuOptions(ActionListenerCommand open, ActionListenerCommand save) {
this.openCommand = open;
this.saveCommand = save;
}
public void clickOpen(){
openCommand.execute();
}
public void clickSave(){
saveCommand.execute();
}
}
客户类别 :
public class Client {
public static void main(String[] args) {
Document doc = new Document();
ActionListenerCommand clickOpen = new ActionOpen(doc);
ActionListenerCommand clickSave = new ActionSave(doc);
MenuOptions menu = new MenuOptions(clickOpen, clickSave);
menu.clickOpen();
menu.clickSave();
}
}
优点:
命令模式有助于解耦调用方和接收方。 接收者是知道如何执行动作的人。
命令应能够执行撤消和重做操作。
这种模式在可扩展性方面有所帮助,因为我们可以在不更改现有代码的情况下添加新命令。
退税:
命令模式的主要缺点是每个单独命令的类数增加。 这些项目也可以通过方法实现来完成。 但是,命令模式类比使用if else条件创建多个方法更具可读性。
有趣的一点:
- java.lang.Runnable和javax.swing.Action的实现遵循命令设计模式。
- 命令可以使用Memento来维护撤消操作所需的状态。
下载示例代码:
参考:来自您的JCG合作伙伴 Mainak Goswami的命令 ,位于Idiotechie博客上。
翻译自: https://www.javacodegeeks.com/2012/11/by-your-command-command-design-pattern.html