目前我正在尝试在一个简单的测试项目中实现事务脚本模式(正是Martin Fowler如何使用Command Pattern 描述),一切正常,问题是我不知道如何在指定时得到结果在具体类中执行的方法,它继承自ICommand接口.
让我们向您展示一些代码,以阐明我的功能.我有一个简单的CalculateSalaryCommand类,它继承自ICommand接口
public class CalculateSalaryCommand : ICommand
{
private readonly CalculateSalaryTS _salaryTs;
private readonly int _hour;
private readonly int _salaryPerHour;
public CalculateSalaryCommand(CalculateSalaryTS salaryTs, int hour, int salaryPerHour)
{
_salaryTs = salaryTs;
_hour = hour;
_salaryPerHour = salaryPerHour;
}
public void Execute()
{
_salaryTs.CalculateSalary(_hour, _salaryPerHour);
}
}
Run Code Online (Sandbox Code Playgroud)
和一个名为CalculateSalaryTS的简单Transaction Script类
public class CalculateSalaryTS {
public void CalculateSalary(int _hour, int _salaryPerHour) {
Result = _hour * _salaryPerHour;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我将实例传递给具体命令类,然后在Execute方法内部执行该实例的操作.好吧,一切都很好看.但有一个问题我无法返回执行方法的结果,应该是一个整数.为了解决这个问题,我决定在Transaction Script层添加一些代码,每个事务应该从一个通用ITransactionResult接口继承,如下所示:
public interface ITransactionResult<TResult>
{
TResult …Run Code Online (Sandbox Code Playgroud) 在命令设计模式中,Invoker类是可选的吗?客户端需要为命令实例化Concrete Command和Receiver.客户端是否总是需要实例化Invoker并将命令对象传递给Invoker对象.稍后当客户端需要执行命令时,客户端只询问Invoker对象并且Invoker执行命令(可能立即或可能将命令排队等待以后执行).
或者这是另一种方式?如果客户端需要同步执行命令,客户端将使用基类接口引用该命令,但将实例化具体的命令和接收器.每当客户端需要执行命令时,客户端只会在基类命令变量上调用execute方法?当一个命令应该执行时需要一些额外的逻辑时,Invoker类将用于保留额外的逻辑,客户端将与Invoker对象进行交互以执行命令?
有一个扩展的命令模式实现,以支持C#中的多命令(组):
var ctx= //the context object I am sharing...
var commandGroup1 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command1(ctx),
new Command2(ctx)
});
var commandGroup2 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command3(ctx),
new Command4(ctx)
});
var groups = new MultiCommand(new List<ICommand>
{
commandGroup1 ,
commandGroup2
}, null);
Run Code Online (Sandbox Code Playgroud)
现在,执行就像:
groups.Execute();
Run Code Online (Sandbox Code Playgroud)
我正在共享相同的上下文(ctx)对象.
Web应用程序的执行计划需要在不同的线程中分离
commandGroup1和commandGroup2分组.具体来说,commandGroup2将在新线程和commandGroup1主线程中执行.
执行现在看起来像:
//In Main Thread
commandGroup1.Execute();
//In the new Thread
commandGroup2.Execute();
Run Code Online (Sandbox Code Playgroud)
如何线程安全地共享相同的内容context object (ctx),以便能够 …
根据该视频在这里 [@ 7:50]谷歌被推荐使用了Command模式,其请求处理API之上.还有一个有用的项目gwt-dispatch实现了这种模式.
根据gwt-dispatch 文档,我需要为每个命令创建四个类:
假设我的服务API在8个BSO中有100个方法,有人可以向我解释为什么我要创建近400个新类吗?这种模式有什么好吃的?
我在我的应用程序中实现了命令模式(以多种支持方式).
结构体:
class MultiCommand : BaseCommand
abstract class BaseCommand : ICommand
Run Code Online (Sandbox Code Playgroud)
流程:
var commandsGroup = new MultiCommand(new List<ICommand>()
{
new Command1(),
new Command2(),
new Command3(),
});
commandsGroup.Execute()
Run Code Online (Sandbox Code Playgroud)
现在,假设在Command1a中somethingID已更改并且我将在Command2...中使用此新值.并且还有许多其他属性和对象在整个执行过程中受到影响.
此外,还有一些接口实现应该可以在任何命令中使用,只需使用上下文对象,如:
Context.ServerController.something();
Run Code Online (Sandbox Code Playgroud)
IServerController将在multiCommandGroup初始化之前进行实例化.
如何为组中的所有命令创建这样的共享上下文?
Context类的示例:
public class CommandContext
{
public IServerController ServerController;
public RequiredData Data { get; set; }
public CommandContext(){}
}
Run Code Online (Sandbox Code Playgroud)
重要信息 最小的实施代码在这里
我想发出一系列命令执行,但只有在前一个命令成功时才会发出.现在我在命令对象中引发一个事件,指示命令是成功还是失败.我用这个来控制执行,但感觉不够优雅.
例:
command1.CommandSucceeded += delegate { command2.Execute(); };
command1.Execute();
Run Code Online (Sandbox Code Playgroud)
这有效,但感觉笨拙和不直观.我可以在Execute()上传回一个布尔值,表示成功或失败,但这是沿着相同的路径.我可以在失败时抛出异常,这可能会导致更清晰的代码,但可能有点过分.
有什么建议?
我正在研究设计模式,我目前正在研究命令模式.
这是我目前的代码:
// this is the receiver
class Calculator : IReceiver
{
int x;
int y;
CommandOptions command;
public Calculator(int x, int y)
{
this.x = x;
this.y = y;
}
public void SetAction(CommandOptions command)
{
this.command = command;
}
public int GetResult()
{
int result = 0;
switch(this.command)
{
case CommandOptions.ADD:
result = this.x + this.y;
break;
case CommandOptions.SUBTRACT:
result = this.x - this.y;
break;
case CommandOptions.MULTIPLY:
result = this.x * this.y;
break;
}
return result;
}
}
// …Run Code Online (Sandbox Code Playgroud) 命令模式用于封装对象中的命令.但为什么不使用函数指针呢?为什么我需要为每个操作子类化Command?相反,我可以有不同的函数并调用函数指针.
我对领域驱动的设计概念相当陌生,我遇到了一个问题,即在使用命令总线和域逻辑的命令和命令处理程序时,在API中返回正确的响应.
假设我们正在使用域驱动设计方法构建应用程序.我们有一个后端和前端部分.后端的所有域逻辑都带有公开的API.前端使用API向应用程序发出请求.
我们使用映射到命令总线的命令和命令处理程序构建域逻辑.在我们的域目录下,我们有一个命令用于创建名为CreatePostCommand的帖子资源.它通过命令总线映射到其处理程序CreatePostCommandHandler.
final class CreatePostCommand
{
private $title;
private $content;
public function __construct(string $title, string $content)
{
$this->title = $title;
$this->content= $content;
}
public function getTitle() : string
{
return $this->title;
}
public function getContent() : string
{
return $this->content;
}
}
final class CreatePostCommandHandler
{
private $postRepository;
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
public function handle(Command $command)
{
$post = new Post($command->getTitle(), $command->getContent());
$this->postRepository->save($post);
}
}
Run Code Online (Sandbox Code Playgroud)
在我们的API中,我们有一个用于创建帖子的端点.这将在我们的Application目录下的PostController中路由createPost方法.
final class PostController
{
private $commandBus;
public function …Run Code Online (Sandbox Code Playgroud) 出于学习目的,我正在尝试将此 Java 命令模式示例迁移到 PHP:
https://codereview.stackexchange.com/questions/52110/command-pattern-implementation
正如@simon 所评论的那样,使用方法引用运算符,可以使代码现代化很多:
class MyCommand implements Order {
private final Runnable action;
public MyCommand(Runnable action) {
this.action = action;
}
@Override
public void execute() {
action.run();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以创建这样的命令:
MyCommand bsc = new MyCommand(stock::buy);
MyCommand ssc = new MyCommand(stock::sell);
Run Code Online (Sandbox Code Playgroud)
我当前的 PHP 实现在这里:https : //3v4l.org/iIHn9
那么在 PHP 中实现MyCommand 类的最佳方法是什么?
command-pattern ×10
c# ×5
java ×2
php ×2
api-design ×1
architecture ×1
gwt ×1
javascript ×1
oop ×1
porting ×1
runnable ×1