2012-06-21 34 views
5

Tôi đã có một đường ống nhiệm vụ về cơ bản là một biến thể của chuỗi mô hình trách nhiệm.Thực hiện chuỗi biến đổi trách nhiệm

Một nhiệm vụ trong đường ống của tôi trông như sau

internal interface IPTask<T> 
{ 
    bool CanExecute(T instance); 
    T Process(T instance); 
} 

..và xử lý của tôi trông giống như

internal interface IProcessor<T> 
{ 
    T Execute(T instance); 
} 

và thực hiện cụ thể của tôi trông như thế này:

public class Processor<T> : IProcessor<T> 
{ 
    private readonly ITasks<T> tasks; 

    public Processor(ITasks<T> tasks) 
    { 
     this.tasks= tasks; 
    } 

    public T Execute(T instance) 
    { 
     var taskstoExecute = tasks.GetTasks() 
            .Where(task => task.CanExecute(instance)); 

     taskstoExecute.ToList().ForEach(task=>task.Process(instance)); 

     return T; 
    } 
} 

.. và nhiệm vụ của tôi trông giống như sau:

internal interface ITasks<T> 
{ 
    IEnumerable<IPTask<T>> GetTasks(); 
} 

T có thể là các trường hợp khác nhau, nhưng bị ràng buộc bởi hợp đồng chung. Một trong các nhiệm vụ là ánh xạ đối tượng đến vào một đối tượng hoàn toàn khác và chuyển tiếp cá thể đó từ đó trở đi.

Bây giờ như bạn sẽ thấy, tôi đang thực hiện tất cả các nhiệm vụ trong các đường ống, tôi muốn sửa đổi này như sau:

  • đầu vào cho phương pháp Execute cho nhiệm vụ tiếp theo nên từ nhiệm vụ được thực hiện trước đó.
  • Nếu CanExecute không thực hiện được nhiệm vụ thì đường ống sẽ ngừng xử lý các tác vụ.

Bạn có thể vui lòng giúp tôi trong việc này. Bạn cũng mong đợi mã được cấu trúc khác nhau cho mục đích này?

Trả lời

3

Làm thế nào về điều này:

public T Execute(T instance) 
{ 
    T result = instance; 
    foreach(var individual in tasks.GetTasks()) 
    { 
     if(!individual.CanExecute()) break; 

     result = individual.Process(result); 
    } 

    return result; 
} 

Như bạn có nó hiện nay, nó là nhiều hơn nữa như một mô hình tổng hợp hơn là một chuỗi các trách nhiệm. Sự thay đổi này khiến CoR-ish thêm một chút. Nhưng điều quan trọng cần lưu ý là liệu nó có đáp ứng nhu cầu của bạn hơn là sử dụng thuật ngữ mẫu thiết kế chính xác hay không. :)

3

Với việc triển khai này, CanProcess thực sự được sử dụng để kích hoạt một ngoại lệ sẽ dừng quá trình.

Tôi đã thêm một triển khai thứ hai, được gọi là ExecuteWithPartial, xử lý ngoại lệ, trong trường hợp đó là hành vi bạn đang mong đợi. Nó xử lý nhưng nếu có lỗi, nó trả về kết quả một phần cho đến điểm đó.

public class Processor<T> : IProcessor<T> 
{ 
    //... rest of your code 

    public T Execute(T instance) 
    { 
     return this._tasks.GetTasks().Aggregate(instance, (current, task) => InternalExecute(task, current)); 
    } 

    public T ExecuteWithPartial(T instance) 
    { 
     var target = instance; 
     try 
     { 
      foreach (var task in this._tasks.GetTasks()) 
      { 
       target = InternalExecute(task, target); 
      } 
      return target; 
     } 
     catch (CantExecuteException) 
     { 
      return target; 
     } 
    } 


    private static T InternalExecute(IPTask<T> task, T instance) 
    { 
     if (!task.CanExecute(instance)) 
      throw new CantExecuteException(); 
     return task.Process(instance); 
    } 
} 

Và các lớp ngoại lệ mới là:

public class CantExecuteException : Exception 
{ 
} 
Các vấn đề liên quan