2012-01-14 4 views
8

현재 간단한 테스트 프로젝트에서 트랜잭션 스크립트 패턴 (정확히 012m)을 구현하려고하는데, 모든 것이 제대로 작동합니다. 문제는 내가하지 않는 곳입니다. (정확히을 Command Pattern으로 사용합니다.) ICommand 인터페이스에서 상속 된 구체적인 클래스에서 지정된 메소드가 실행될 때 결과를 얻는 방법을 알아야합니다.명령 패턴에서 실행 된 메서드의 결과 얻기

내가 갖고있는 기능을 명확하게 설명하는 코드를 보여 드리겠습니다. 나는 이름 CalculateSalaryTS 당신은 내가 다음, 콘크리트 명령 클래스의 인스턴스를 전달 볼 수

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

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); 
    } 
} 

간단한 트랜잭션 스크립트 클래스에서 상속 간단한 CalculateSalaryCommand 클래스를했습니다 Execute 메서드 내에서 해당 인스턴스에서 작업을 실행합니다. 글쎄, 모든게 잘 어울려. 하지만 정수가되어야하는 실행 된 메소드의 결과를 리턴 할 수없는 문제점이 있습니다.

:

다음
public interface ITransactionResult<TResult> 
{ 
    TResult Result { get; set; } 
} 

CalculateSalaryTS 클래스는 다음과 같이되었다 : 이 문제를 처리하기 위해, 나는 다음과 같이 각 트랜잭션이 일반적인 ITransactionResult 인터페이스에서 상속해야 트랜잭션 스크립트 층에 일부 코드를 추가하기로 결정

public class CalculateSalaryTS : ITransactionResult<Int32> { 

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

    public int Result { get; set; } 

} 

사용법 :

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

이 방법에는 한계가 있지만이 상황을 처리하기위한 또 다른 아이디어를 줄 때까지는 선택의 여지가 없습니다.

미리 감사드립니다.

답변

18

그래서 :

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); 
+0

Dennis 님의 회신에 감사드립니다. 당신은 훌륭한 솔루션을 선호했습니다. 그러나 패턴의 개념을 디자인하는 것이 새로운 것이기 때문에 ICommand 동작에 추가 기능을 추가하는 것에 대해 혼란스러워합니다. 맞습니까? – saber

+2

필요에 따라 명령을 확장하는 데 문제가 있다고 생각하지 않습니다. 디자인 패턴은 특정 문제와 반복되는 문제를 해결하는 방법에 대한 지침입니다. 그것들은 돌에 세워져있는 것이 아니라 오히려 당신이 만들 수있는 기초입니다. 특별한 경우에는 'ICommandWithResult '인터페이스를 추가 할 필요가 없습니다. 'ICommand'에'Result' 속성을'CalculateSalaryClass'에 추가하면됩니다. –

+0

+1 데니스 감사합니다. – saber

4

결과를 반환 할 수있는 명령 패턴을 찾고 있다고 생각합니다. 당신이 절대적으로 명령 실행 후 즉시 결과를 얻을 필요가 있다면, 당신은 명령 개체에 결과를 저장할 수

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); 
    } 
} 
+2

명령 패턴의 방법은 무효가해야을하자 당신이 옳다고 상상해보십시오. 내가 무효화 된 방법을 실행하고 싶다면 어떨까요? 나는 어떻게해야합니까? – saber

+0

@SaberAmani : 두 가지 방법으로, null을 반환하는 ICommand 을 구현하거나'GetResult()'라는 메서드/속성을 구현합니다. – Spoike