Ext*_*kun 118 encapsulation design-patterns strategy-pattern command-pattern
两种设计模式都封装了算法,并将实现细节与其调用类分离.我能辨别的唯一区别是策略模式接受执行参数,而命令模式则没有.
在我看来,命令模式要求所有执行信息在创建时都可用,并且它能够延迟其调用(可能作为脚本的一部分).
什么决定指导是使用一种模式还是另一种模式?
Hup*_*tes 91
我将包含几个GoF设计模式的封装层次表,以帮助解释这两种模式之间的差异.希望它能更好地说明每个封装的内容,因此我的解释更有意义.
首先,层次结构列出了给定模式适用的范围,或者用于封装某些细节级别的适当模式,具体取决于您从哪个表开始.

从表中可以看出,策略模式对象隐藏了算法实现的细节,因此使用不同的策略对象将以不同的方式执行相同的功能.每个策略对象可以针对特定因素进行优化,或者针对其他一些参数进行操作; 并且,通过使用公共接口,上下文可以安全地使用.
命令模式封装了比算法小得多的细节.它编码将消息发送到对象所需的详细信息:接收器,选择器和参数.客观化执行流程执行的这么一小部分的好处是,可以以一般方式在不同时间点或位置调用此类消息,而无需对其详细信息进行硬编码.它允许一次或多次调用消息,或者传递给系统的不同部分或多个系统,而不需要在执行之前知道特定调用的细节.
对于设计模式而言,它们通常不要求所有实现在细节上都具有相同的模式名称.细节可以在实现中以及在对象中编码的数据与方法参数之间变化.
Pau*_*bel 48
策略封装了算法.命令将发送方与请求的接收方分开,它们将请求转换为对象.
如果是算法,将如何完成某项任务,请使用策略.如果需要将方法的调用与其执行分开,请使用命令.排队消息供以后使用时,通常会使用命令,如任务或事务.
rpa*_*abi 25
回答一个非常古老的问题.(有人看到最新的答案,而不是大多数人投票?)
由于相似之处,这是一个有效的混淆.策略和命令模式都使用封装.但这并不能使它们相同.
关键的区别是要了解什么是封装.两种模式依赖的OO原则是封装变化的内容.
在策略的情况下,不同的是算法.例如,一个策略对象知道如何输出到XML文件,而另一个策略对象输出到JSON.不同的算法保存(封装)在不同的类中.它是如此简单.
在命令的情况下,请求本身有所不同.请求可能来自File Menu > Delete或Right Click > Context Menu > Delete或Just Delete Button pressed.这三种情况都可以生成3个相同类型的命令对象.这些命令对象仅代表3个删除请求; 不删除算法.由于请求现在是一堆对象,我们可以轻松地管理它们.突然间,提供撤消或重做等功能变得微不足道.
命令如何实现所请求的逻辑并不重要.在调用execute()时,它可以实现一个触发删除的算法,或者甚至可以将它委托给其他对象,甚至可以委托给一个策略.它只是命令模式的实现细节.这就是为什么它被命名为命令虽然它不是一种礼貌的方式来请求: - )
将其与战略进行对比; 这种模式只关注执行的实际逻辑.如果我们这样做,它有助于用最少的类集实现不同的行为组合,从而防止类爆炸.
我认为,Command帮助我们拓宽了对封装的理解,而Strategy提供了封装和多态的自然使用.
MSt*_*odd 15
我看待它的方式是你有多种方法做同样的事情,每个方法都是一个策略,运行时的东西决定了哪个策略被执行.
也许首先尝试使用StrategyOne,如果结果不够好,请尝试使用StrategyTwo ...
命令绑定到需要发生的不同事情,如TryToWalkAcrossTheRoomCommand.每当某个对象试图穿过房间时,该命令将被触发,但在其中,它可能会尝试使用StrategyOne和StrategyTwo来试图穿过房间.
标记
在我看来,我可能是错的,但我将命令视为执行功能或反应.应该至少有两个参与者:请求操作的人和执行操作的人.GUI是命令模式的典型示例:
该命令通常限制在某个范围或业务范围内,但不是必需的:您可能拥有execute()在一个应用程序中发出帐单,启动火箭或删除实现相同接口(例如单个方法)的文件的命令.通常命令是自包含的,因此它们不需要执行程序中的任何内容来处理它们打算执行的任务(所有必要的信息都是在构造时给出的),有时命令是上下文敏感的并且应该能够发现这种上下文(Backspace命令应该知道文本中的插入符位置以正确删除前一个字符; Rollback命令应该发现要回滚的当前事务; ...).
该战略是一个有点不同:它更绑定到其他区域.策略可以定义规则来格式化日期(以UTC?区域设置特定?)("日期格式化程序"策略)或计算几何图形的平方("方形计算器"策略).从这个意义上说,策略是轻量级对象,它将某些东西作为输入("日期","数字",......)并在其基础上做出一些决定.也许不是最好的,但良好的战略的例子是一个具有连接javax.xml.transform.Source接口:根据传递的对象是否是DOMSource或SAXSource或StreamSource策略(=在这种情况下,XSLT转换器)将适用不同的规则来处理它.实施可以是简单的switch或涉及责任链模式.
但实际上这两种模式之间存在共同点:命令和策略将算法封装在同一语义区域内.
命令:
基本组件:
execute()工作流程:
客户端调用Invoker => Invoker调用ConcreteCommand => ConcreteCommand调用Receiver方法,该方法实现抽象的Command方法。
优点:客户端不受命令和接收器更改的影响。Invoker 在 Client 和 Receiver 之间提供松散耦合。您可以使用同一个 Invoker 运行多个命令。
命令模式允许您使用相同的Invoker在不同的接收器上执行命令。调用者不知道接收者的类型
为了更好地理解概念,看看这个JournalDev文章由潘卡·库马尔和dzone文章由詹姆斯Sugrue除了维基百科的链接。
您可以使用命令模式来
解耦命令的调用者和接收者
实现回调机制
实现撤销和重做功能
维护命令的历史记录
java.lang.Thread是命令模式的一种很好的实现。您可以将Thread视为调用者和类,将Runnable视为ConcreteCommonad/Receiver并将run()方法视为Command。
可以在Theodore Norvell 的 文章中阅读命令模式的撤消/重做版本
战略:
策略模式很容易理解。使用此模式时
一个算法有多个实现,并且算法的实现可以根据特定条件在运行时更改。
以航空公司预订系统的票价组件为例
航空公司希望在不同的时间段(高峰和非高峰月份)提供不同的票价。在非高峰旅行日,它希望通过提供有吸引力的折扣来刺激需求。
策略模式的关键要点:
带有代码示例的相关帖子: