命令设计模式是一种广为人知的设计模式,它属于行为设计模式(“四人帮”的一部分)。 顾名思义,它与应用程序中的动作和事件有关。
问题陈述:
假设有一个网页将在其中包含多个菜单的情况。 编写此代码的一种方法是使条件成立,并在每次单击菜单时执行操作。
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;}@Overridepublic 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