C#与代表的责任链

时间:2010-04-14 08:21:11

标签: c# chain-of-responsibility

出于我的理解目的,我实施了责任链模式。

//Abstract Base Type

public abstract class CustomerServiceDesk
{
 protected CustomerServiceDesk _nextHandler;
 public abstract  void ServeCustomers(Customer _customer);
 public void SetupHadler(CustomerServiceDesk _nextHandler)
 {
          this._nextHandler = _nextHandler;
 }
}

 public class FrontLineServiceDesk:CustomerServiceDesk
 {
     public override void ServeCustomers(Customer _customer)
     {
        if (_customer.ComplaintType == ComplaintType.General)
         {
           Console.WriteLine(_customer.Name + " Complaints are registered  ; 
           will be served soon by FrontLine Help Desk..");
         }

        else 
        {
          Console.WriteLine(_customer.Name + " 
          is redirected to Critical Help Desk");

          _nextHandler.ServeCustomers(_customer);
        }

        }
  }
public class CriticalIssueServiceDesk:CustomerServiceDesk
{
    public override void ServeCustomers(Customer _customer)
    {
        if (_customer.ComplaintType == ComplaintType.Critical)
        {
            Console.WriteLine(_customer.Name + 
            "Complaints are registered  ; will be served soon 
             by Critical Help Desk");
        }
        else if (_customer.ComplaintType == ComplaintType.Legal)
        {
            Console.WriteLine(_customer.Name +
            "is redirected to Legal Help Desk");
            _nextHandler.ServeCustomers(_customer);
        }
    }
}

public class LegalissueServiceDesk :CustomerServiceDesk
{
    public override void ServeCustomers(Customer _customer)
    {
        if (_customer.ComplaintType == ComplaintType.Legal)
        {
            Console.WriteLine(_customer.Name + 
            "Complaints are registered  ; 
             will be served soon by legal help desk");
        }
    }
}


public class Customer
{
    public string Name { get; set; }
    public ComplaintType ComplaintType { get; set; }
}


public enum ComplaintType
{
    General,
    Critical,
    Legal
}

void Main()
{
CustomerServiceDesk _frontLineDesk = new FrontLineServiceDesk();
CustomerServiceDesk _criticalSupportDesk = new CriticalIssueServiceDesk();
CustomerServiceDesk _legalSupportDesk = new LegalissueServiceDesk();
_frontLineDesk.SetupHadler(_criticalSupportDesk);
_criticalSupportDesk.SetupHadler(_legalSupportDesk);

Customer _customer1 = new Customer();
_customer1.Name = "Microsoft";
_customer1.ComplaintType = ComplaintType.General;

Customer _customer2 = new Customer();
_customer2.Name = "SunSystems";
_customer2.ComplaintType = ComplaintType.Critical;

Customer _customer3 = new Customer();
_customer3.Name = "HP";
_customer3.ComplaintType = ComplaintType.Legal;

_frontLineDesk.ServeCustomers(_customer1);
_frontLineDesk.ServeCustomers(_customer2);
_frontLineDesk.ServeCustomers(_customer3);
}

问题

在不破坏责任链的情况下,我如何应用委托和事件来重写代码?

3 个答案:

答案 0 :(得分:9)

如果我理解正确...您可以执行的操作是删除SetupHandler方法,并在您的OnElevateQuery对象处理CriticalHelpDesk事件时引入FrontLineHelpDesk.OnElevateQuery事件并且您的LegalHelpDesk对象可以处理CriticalHelpDesk.OnElevateQuery事件。 OnElevateQuery事件可以在事件args中传递客户。

实施例

public abstract class CustomerServiceDesk
{
    public delegate void ElevateQueryEventHandler(Customer c);
    public event ElevateQueryEventHandler OnElevateQuery;
    public abstract void ServeCustomer(Customer c);
}

public class FrontLineServiceDesk : CustomerServiceDesk
{
    public override void ServeCustomer(Customer c)
    {
        switch (c.ComplaintType)
        {
            case ComplaintType.General:
                Console.WriteLine(c.Name + " Complaints are registered; will be served soon by FrontLine Help Desk");
                break;
            default:
                OnElevateQuery(c);
        }
    }
}

public class CriticalIssueServiceDesk : CustomerServiceDesk
{
    public override void ServeCustomer(Customer c)
    {
        switch (c.ComplaintType)
        {
            case ComplaintType.Critical:
                Console.WriteLine(c.Name + " Complaints are registered; will be served soon by Critical Help Desk");
                break;
            case ComplaintType.Legal:
                OnElevateQuery(c);
                break;
            default:
                Console.WriteLine("Unable to find appropriate help desk for your complaint.");
                break;
        }
    }
}

public class LegalIssueServiceDesk : CustomerServiceDesk
{
    public override void ServeCustomer(Customer c)
    {
        if (c.CompliantType == CompliantType.Legal)
        {
            Console.WriteLine(c.Name + " Complaints are registered; will be served soon by Legal Help Desk");
        }
        else
        {
            // you could even hook up the FrontLine.ServeCustomer event 
            // to the OnElevateQuery event of this one so it takes the 
            // query back to the start of the chain (if it accidently ended up here).
            Console.WriteLine("Wrong department");
        }
    }
}

用法

CustomerServiceDesk _frontLine = new FrontLineServiceDesk();
CustomerServiceDesk _criticalLine = new CriticalLineServiceDesk();
CustomerServiceDesk _legalLine = new LegalLineServiceDesk();
// hook up events
_frontLine.OnElevateQuery += _critialLine.ServeCustomer;
_criticalLine.OnElevateQuery += _legalLine.ServeCustomer;

Customer _customer1 = new Customer(); 
_customer1.Name = "Microsoft"; 
_customer1.ComplaintType = ComplaintType.General; 

Customer _customer2 = new Customer(); 
_customer2.Name = "SunSystems"; 
_customer2.ComplaintType = ComplaintType.Critical; 

Customer _customer3 = new Customer(); 
_customer3.Name = "HP"; 
_customer3.ComplaintType = ComplaintType.Legal;

_frontLine.ServeCustomer(_customer1);
_frontLine.ServeCustomer(_customer2);
_frontLine.ServeCustomer(_customer3);

但是,由于查询类型基于枚举ComplaintType,您考虑使用可能返回通用接口的HelpDeskFactory,例如IHelpDesk。对于这个特定的例子,听起来你也可以使用策略模式

答案 1 :(得分:3)

拥有complaintType的客户看起来像是错位的属性。我认为你的意思是投诉有一个类型。

我可能错了,在哪种情况下你可以指出缺少什么行为 这对我来说就像是一件大事。将按订阅顺序调用每个事件处理程序。每个处理程序都可以根据投诉自由忽略通知。只要eventArgs的Handled属性为false并且有待处理的订阅者,就会调用下一个处理程序。

class ComplaintSource
{
  public delegate void ComplaintHandler(Complaint complaint, HandledEventArgs evtArgs);
  public event ComplaintHandler NewComplaint;

  // code that raises the NewComplaint event as appropriate.
   public void DoStuffThatRaisesTheEvent()
    {
        var evtArgs = new HandledEventArgs();
        var theComplaint = new Complaint();
        if (null == this.NewComplaint)
            return;

        Delegate[] list = NewComplaint.GetInvocationList();
        foreach (Delegate del in list)
        {
            if (evtArgs.Handled)
                break;
            ComplaintHandler handler = (ComplaintHandler)del;
            handler(theComplaint, evtArgs);
        }
    }
}

class FrontLineServiceDesk
{
  FrontLineServiceDesk(ComplaintSource source)
  { source.NewComplaint += HandleGeneralComplaint; }
  void HandleGeneralComplaint(Complaint complaint, HandledEventArgs evtArgs) { ... 
    // set evtArgs.Handled = true if you've handled the complaint
    // this will stop the chain
  }
}

class CriticalIssueServiceDesk
{
  CriticalIssueServiceDesk(ComplaintSource source)
  { source.NewComplaint += HandleGeneralComplaint; }
  void HandleCriticalComplaint(Complaint complaint, HandledEventArgs evtArgs) { ... }
}

// finally set the ball in motion

var source = new CompaintSource();
var frontLineDesk = new FrontLineServiceDesk(source);
var criticalIssueDesk = new CriticalIssueServiceDesk(source);

source.DoStuffThatRaisesTheEvent();

答案 2 :(得分:-1)

这与上面的答案非常相似,但更加精简。 :)

public abstract class CustomerServiceDesk
{
    protected CustomerServiceDesk()
    {
        ServeCustomers = doServeCustomers;
    }

    protected CustomerServiceDesk m_ServiceDesk = null;
    protected abstract void doServeCustomers(Customer _customer);

    public delegate void ServeCustomersDelegate(Customer _customer);
    public ServeCustomersDelegate ServeCustomers = null;
}

public class LegalissueServiceDesk : CustomerServiceDesk
{
    public LegalissueServiceDesk()
    {
    }

    protected override void doServeCustomers(Customer _customer)
    {
        if (_customer.ComplaintType == ComplaintType.Legal)
        {
            Console.WriteLine(_customer.Name + " - Complaints are registered  ; will be served soon by legal help desk.\n");
        }
    }
}

public class CriticalIssueServiceDesk : CustomerServiceDesk
{
    public CriticalIssueServiceDesk()
    {
        m_ServiceDesk = new LegalissueServiceDesk();
        ServeCustomers += m_ServiceDesk.ServeCustomers;
    }

    protected override void doServeCustomers(Customer _customer)
    {
        if (_customer.ComplaintType == ComplaintType.Critical)
        {
            Console.WriteLine(_customer.Name + " - Complaints are registered  ; will be served soon by Critical Help Desk.\n");
        }
    }
}

public class FrontLineServiceDesk : CustomerServiceDesk
{
    public FrontLineServiceDesk()
    {
        m_ServiceDesk = new CriticalIssueServiceDesk();
        ServeCustomers += m_ServiceDesk.ServeCustomers;
    }

    protected override void doServeCustomers(Customer _customer)
    {
        if (_customer.ComplaintType == ComplaintType.General)
        {
            Console.WriteLine(_customer.Name + " - Complaints are registered  ; will be served soon by FrontLine Help Desk.\n");
        }
    }
}

public class Customer
{
    public string Name;
    public ComplaintType ComplaintType;
}

public enum ComplaintType
{
    General,
    Critical,
    Legal
}

class Program
{
    static void Main(string[] args)
    {
        Customer _customer1 = new Customer();
        _customer1.Name = "Microsoft";
        _customer1.ComplaintType = ComplaintType.General;

        Customer _customer2 = new Customer();
        _customer2.Name = "SunSystems";
        _customer2.ComplaintType = ComplaintType.Critical;

        Customer _customer3 = new Customer();
        _customer3.Name = "HP";
        _customer3.ComplaintType = ComplaintType.Legal;

        FrontLineServiceDesk _frontLineDesk = new FrontLineServiceDesk();

        _frontLineDesk.ServeCustomers(_customer1);
        _frontLineDesk.ServeCustomers(_customer2);
        _frontLineDesk.ServeCustomers(_customer3);

        Console.In.ReadLine();
    }
}