在Command Pattern中获取执行方法的结果

sab*_*ber 11 c# architecture design-patterns command-pattern

目前我正在尝试在一个简单的测试项目中实现事务脚本模式(正是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 Result { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后CalculateSalaryTS类变成这样:

public class CalculateSalaryTS : ITransactionResult<Int32> {

    public void CalculateSalary(int _hour, int _salaryPerHour) {
        Result = _hour * _salaryPerHour;
    }

    public int Result { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

用法:

    var script = new CalculateSalaryTS();
    var command = new CalculateSalaryCommand(script, 10, 20);           
    command.Execute();
    Console.WriteLine("Salary is {0}", script.Result);
Run Code Online (Sandbox Code Playgroud)

我知道这种方式有其自身的局限性但我没有任何选择,直到你给我另一个想法来处理这种情况.

提前致谢.

Den*_*aub 22

如果您在命令执行后绝对需要立即获得结果,则可以将结果存储在命令对象中:

public interface ICommandWithResult<T> : ICommand
{
  T Result { get; }
}

public class CalculateSalaryCommand : ICommandWithResult<int>
{
  public int Result { get; private set; }

  // ...

  public void Execute()
  {
    _salaryTs.CalculateSalary(_hour, _salaryPerHour);
    this.Result = _salaryTs.Result;
  }
}

// Usage:

var command = new CalculateSalaryCommand(new CalculateSalaryTS(), 10, 20);
command.Execute();
Console.WriteLine("Salary is {0}", command.Result);
Run Code Online (Sandbox Code Playgroud)

  • 我认为根据需要扩展命令不会有问题.设计模式是指如何解决特定和反复出现的问题的指导.它们不是一成不变的,而是你可以建立的基础.在您的特定情况下,您甚至不需要添加接口`ICommandWithResult <T>`.你可以只需要`ICommand`将`Result`属性添加到`CalculateSalaryClass`中. (4认同)
  • 我认为命令模式的力量在于您将控制流传递给另一个组件,让它决定执行的时间表(例如放入队列)。但是如果你传递控制流,你就会失去返回值。如果您想立即执行命令并获取返回值,则不需要使用命令模式。 (3认同)

Man*_*ani 6

我认为您正在寻找一种能够返回结果的命令模式。

所以,

    interface ICommand<TResult>
    {
       TResult Execute();
    }


public class CalculateSalaryCommand : ICommand<int>
{
    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 int Execute()
    {
        return _salaryTs.CalculateSalary(_hour, _salaryPerHour);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 命令模式的方法应该是空的,让我们想象你是对的,如果我想执行一个无效的方法呢?我该怎么办 ? (3认同)