两种设计模式都封装了算法,并将实现细节与其调用类分离.我能辨别的唯一区别是策略模式接受执行参数,而命令模式则没有.
在我看来,命令模式要求所有执行信息在创建时都可用,并且它能够延迟其调用(可能作为脚本的一部分).
什么决定指导是使用一种模式还是另一种模式?
encapsulation design-patterns strategy-pattern command-pattern
对不起,我找不到回答这个问题的问题,我几乎可以肯定其他人已经提出了这个问题.
我的问题是我正在编写一些系统库来运行嵌入式设备.我有命令可以通过无线电广播发送到这些设备.这只能通过文字来完成.在系统库中我有一个线程来处理看起来像这样的命令
if (value.equals("A")) { doCommandA() }
else if (value.equals("B")) { doCommandB() }
else if etc.
Run Code Online (Sandbox Code Playgroud)
问题是它有很多命令会迅速失控.看起来很可怕,调试很痛苦,并且在几个月的时间里难以理解.
我一直在寻找一个很好的解决方案来解决典型的Repository模式所带来的问题(专门的查询方法的增长列表等等.请参阅:http://ayende.com/blog/3955/repository-是新单身人士).
我非常喜欢使用Command查询的想法,特别是通过使用规范模式.但是,我的规范问题是它只涉及简单选择的标准(基本上是where子句),而不涉及查询的其他问题,例如连接,分组,子集选择或投影等.基本上,许多查询必须通过所有额外的箍来获得正确的数据集.
(注意:我在命令模式中使用术语"命令",也称为查询对象.我不是在命令/查询分离中讨论命令,其中查询和命令之间存在区别(更新,删除,插入))
因此,我正在寻找封装整个查询的替代方案,但仍然足够灵活,以至于您不仅仅需要交换spaghetti Repositories以进行大量的命令类.
我已经使用过,例如Linqspecs,虽然我发现能够为选择标准指定有意义的名称有一些价值,但这还不够.也许我正在寻找一种结合多种方法的混合解决方案.
我正在寻找其他人可能已经开发的解决方案,以解决这个问题,或解决不同的问题,但仍满足这些要求.在链接的文章中,Ayende建议直接使用nHibernate上下文,但我觉得这很大程度上使您的业务层复杂化,因为它现在还必须包含查询信息.
等待期过后,我会在此提供赏金.因此,请提供有价值的解决方案,并提供良好的解释,我将选择最佳解决方案,并向选手投票.
注意:我正在寻找基于ORM的东西.不必明确是EF或nHibernate,但这些是最常见的并且最适合.如果它可以很容易地适应其他ORM,那将是一个奖励.Linq兼容也不错.
更新:我真的很惊讶这里没有很多好的建议.似乎人们完全是CQRS,或者他们完全在资源库中.我的大多数应用程序都不够复杂,无法保证CQRS(大多数CQRS倡导者都会说你不应该使用它).
更新:这里似乎有点混乱.我不是在寻找新的数据访问技术,而是在业务和数据之间设计合理的界面.
理想情况下,我正在寻找的是Query对象,规范模式和存储库之间的某种交叉.正如我上面所说,规范模式只处理where子句方面,而不是查询的其他方面,如连接,子选择等.存储库处理整个查询,但一段时间后失控.查询对象也处理整个查询,但我不想简单地用查询对象的爆炸替换存储库.
我的问题与命令模式有关,我们有以下抽象(C#代码):
public interface ICommand
{
void Execute();
}
Run Code Online (Sandbox Code Playgroud)
让我们来看一个简单的具体命令,它旨在从我们的应用程序中删除一个实体.Person例如,一个实例.
我会有一个DeletePersonCommand实现的ICommand.此命令需要Person删除作为参数,以便在Execute调用方法时将其删除.
管理参数化命令的最佳方法是什么?在执行参数之前如何将参数传递给命令?
关于命令是否应该具有返回值似乎存在无穷无尽的混淆.我想知道这种混乱是否仅仅是因为参与者没有陈述他们的背景或情况.
以下是混淆的例子......
Udi Dahan说命令"不会向客户端返回错误",但在同一篇文章中他展示了一个图表,其中命令确实将错误返回给客户端.
微软新闻商店文章指出"命令......不会返回响应",但接着提出了一个含糊不清的警告:
随着围绕CQRS的战场经验的增长,一些实践巩固并倾向于成为最佳实践.部分地与我们刚才所说的相反......今天人们普遍认为命令处理程序和应用程序都需要知道事务操作是如何进行的.必须知道结果......
那么,命令处理程序是否返回值?
从Jimmy Bogard的" CQRS神话 "中得到启示,我认为这个问题的答案取决于你所说的程序/语境"象限":
+-------------+-------------------------+-----------------+
| | Real-time, Synchronous | Queued, Async |
+-------------+-------------------------+-----------------+
| Acceptance | Exception/return-value* | <see below> |
| Fulfillment | return-value | n/a |
+-------------+-------------------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
命令"Acceptance"主要指验证.推测验证结果必须与调用者同步,无论命令"履行"是同步还是排队.
但是,似乎许多从业者不会从命令处理程序中启动验证.从我所看到的,它要么是因为(1)他们已经找到了在应用层处理验证的绝妙方法(即ASP.NET MVC控制器通过数据注释检查有效状态)或者(2)架构假设命令被提交给(进程外)总线或队列.后面这些异步形式通常不提供同步验证语义或接口.
简而言之,许多设计人员可能希望命令处理程序将验证结果作为(同步)返回值提供,但它们必须遵守它们使用的异步工具的限制.
关于命令的"履行",发出命令的客户端可能需要知道新创建的记录的scope_identity或者可能需要知道故障信息 - 例如"帐户透支".
在实时设置中,似乎返回值最有意义; 不应使用例外来传达与业务相关的失败结果.但是,在"排队"环境中......返回值自然没有意义.
这是所有困惑可能总结的地方:
许多(大多数?)CQRS从业者假设他们现在或将来会合并异步框架或平台(总线或队列),从而宣称命令处理程序没有返回值.但是,一些从业者无意使用此类事件驱动的构造,因此他们将支持(同步)返回值的命令处理程序.
因此,例如,我相信Jimmy Bogard提供此示例命令界面时会假设同步(请求 - 响应)上下文:
public interface ICommand<out TResult> { }
public interface ICommandHandler<in TCommand, out TResult>
where TCommand : …Run Code Online (Sandbox Code Playgroud) 我正在研究命令设计模式,我对使用它的方式很困惑.我的示例与用于打开和关闭灯的远程控制类有关.
我为什么不应该使用合闸合闸()/关机灯类,而不是单独的类和方法,最终调用合闸合闸/关机方法()方法?
我知道我的例子很简单,但这就是重点.我无法在Internet上的任何地方找到任何复杂的问题来查看命令设计模式的确切用法.
如果你知道,你解决了可以使用这种设计模式请与我共享来解决任何复杂的现实世界的问题.它帮助我和这篇文章的未来读者更好地理解这种设计模式的用法.谢谢
//Command
public interface Command {
public void execute();
}
//Concrete Command
public class LightOnCommand implements Command {
//Reference to the light
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.switchOn(); //Explicit call of selected class's method
}
}
//Concrete Command
public class LightOffCommand implements Command {
//Reference to the light
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.switchOff();
}
} …Run Code Online (Sandbox Code Playgroud) 有一次我讨论了设计,相对于命令模式.我的同行声明在调用.execute()方法后,命令对象不应返回状态(成功,不成功以及原因).原因是您不应该关心命令是否被执行,因为该命令必须不包含任何状态.但是,如果命令具有预期效果,则必须在调用后进行检查.他认为另一点是,在四人帮中,命令模式并不呈现这种情况(返回状态).
我声称相反的观点.GoF不会出现这种情况,但可以根据您的需要对模式进行建模.如果命令不成功,则调用客户端必须接收状态证明,并最终部署适当的反应.通过强制客户端检查操作是否成功是否容易出错并产生重复的代码.此外,在某些情况下,命令会产生一个结果(例如,一个向绘图添加一行的命令,将以某种方式将行ID返回给客户端),并假装没有状态的命令意味着你必须从数据模型中"捞出"新的对象标识符.
最后,我们通过不返回状态但保持命令对象中新创建的对象的id来达成妥协,并且应用程序仍然运行良好,但我现在很想知道您的意见.
我一直在阅读使用Command对象来表示我们的域公开的用例,以及Command Handler对象来处理这些命令.
例如:
RegisterUserCommandRegisterUserCommandHandler但它看起来与a具有完全相同RegisterUserService,其中命令对象将表示registerUser()方法的参数.
当然,如果方法有太多的参数,我最终会创建一个对象来包装它们,并且该对象与它相同RegisterUserCommand.
那么为什么有不同的模式来表示同样的事情呢?服务很普遍,而不是命令(根据我的经验); 我错过了什么区别?简而言之,为什么我会使用一个而不是另一个?
我正在尝试设计一个异步框架,并想知道人们认为回调模式与观察者模式的优缺点.
Callback pattern:
//example callback
public interface Callback{
public void notify(MethodResult result);
}
//example method
public class Worker{
public void doAsyncWork(Callback callback){
//do work
callback.notify(result);
}
}
//example observer pattern
public interface EventListener{
public void notify(MethodResult result);
}
public class Worker{
private EventListener listener;
public registerEventListener(EventListener listener){
this.listener=listener;
}
public void doAsyncWork(){
//do work
listener.notify(result);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用一个似乎使用这两种模式的框架.EventListener模式不是典型模式,因为它没有监听器列表.这可以通过创建CompositeListener来轻松实现,CompositeListener在侦听器的优先级上有自己的语义,以及如何处理事件到每个侦听器的分布,例如为每个侦听器和串行通知生成新线程.(我实际上认为这是一个好主意,因为它是一个很好的关注点分离,并且是对标准观察者/监听器模式的改进).
你何时应该使用它们?
Thxs.
design-patterns asynchronous callback command-pattern observer-pattern