在Chain of Responsibility模式中的对象之间传递数据

时间:2011-03-18 08:02:07

标签: c# design-patterns

在实施责任链模式时,我遇到了如何在链中的对象之间传递数据的困境。在链中的对象之间传递的数据类型可以针对每个对象而不同。作为临时修复,我创建了一个包含堆栈的Static类,其中链中的每个对象都可以将结果推送到堆栈,而链中的下一个对象可以从堆栈中弹出结果。以下是我实施的示例代码。

public interface IHandler
{        
  IHandler Successor {get; set; }
  void Process();        
}

//Temporary Data Container class to store objects\data    
public static class StackManager
{
  public static Stack DataStack = new Stack();
}

//This class doesn't require any input to operate
public class OpsA : IHandler
{
  public IHandler Successor {get; set; }
  public void Process()
   {
      //Do some processing, store the result into Stack
      var ProcessedData = DoSomeOperation();
      StackManager.DataStack.Push(ProcessedData);

      if(Successor != null) Successor();            
  }
}

//This class require input data to operate upon
public class OpsB : IHandler
{
  public IHandler Successor {get; set; }
  public void Process()
  {
      //Retrieve the results from the previous Operation
      var InputData =  StackManager.DataStack.Pop();

      //Do some processing, store the result into Stack
      var NewProcessedData = DoMoreProcessing(InputData);      
      StackManager.DataStack.Push(NewProcessedData);

      if(Successor != null) Successor();
  }
}

public class ChainOfResponsibilityPattern
{
  public void Process()
  {
       IHandler ProcessA = new  OpsA();  
       IHandler ProcessB = new  OpsB();

       ProcessA.Successor = ProcessB;
       ProcessA.Process();
  }
}

请帮助我找到一种更好的方法来在链中的处理程序之间传递数据。

3 个答案:

答案 0 :(得分:5)

如果您有责任链,这通常涉及单个上下文,因此一个好方法是传递Context对象。

我要注意的一件有趣的事情是围绕上下文的可变性。

您可以拥有一个可变的上下文,然后您将实例化上下文对象,将其传递给ProcessorAProcessorA可以修改它并设置自己的数据,然后将其传递给ProcessorB。然后ProcessorB再修改一次,最后调用者可以读取上下文。

如果您希望获得更多数据安全性并将每个Processor的行为封装为输入到输出黑盒,则可以选择不可变的上下文对象。 ProcessorA可能会收到一个空的上下文对象,然后为ProcessorB构建一个并返回ProcessorB的输出。

答案 1 :(得分:4)

IHandler.Process()方法添加一个参数以便单个对象通过整个链,并使链中的每个条目都使用并根据需要改变传递的对象,这将更加标准。这个对象可能是你的堆栈,但依赖于先前的条目将某些内容推入堆栈仍然会使处理器高度相互依赖。

有关您实际所做工作的更多细节,我们或许能够提出更好的方法,而且责任链可能不恰当。

答案 2 :(得分:1)

为什么不传递一个词典,甚至传递一个列表?