2010-04-14 33 views
5

为了我的理解目的,我实施了职责链模式。C#与代表责任链

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

问题

没有打破链的责任,如何申请委托和事件重写代码?

回答

7

如果我理解正确的话......你可以做的是去除SetupHandler方法,并介绍了OnElevateQuery事件是你CriticalHelpDesk对象可以处理FrontLineHelpDesk.OnElevateQuery事件和你LegalHelpDesk对象可以处理CriticalHelpDesk.OnElevateQuery事件。事件参数中的OnElevateQuery事件可以通过客户。

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。听起来像你也可以使用策略模式这个特定的例子。

+0

优秀的解释,感谢您建议HelpDeskFactory。 – user274364 2010-04-14 09:07:49

+0

@nettguy:没问题:) – James 2010-04-14 09:15:38

2

拥有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(); 
+3

他试图理解责任链,而不是编写最好的代码来完成这项工作。 – 2010-04-14 09:01:09

+0

@Gishu非常感谢你 – user274364 2010-04-14 09:08:28

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

喜欢简化版比其他更长的事实。在没有开玩笑的一面,这个版本对阶段进行了硬编码。例如要在链中添加新的中间步骤,您必须修改现有的类 - 更重要的是,每个阶段都有关于下一个阶段的知识(并且在此情况下包含/创建它)。我会放松这里的耦合。 – Gishu 2010-04-14 09:59:16

+0

是的,我同意。其更多的设计变化。这样说似乎是合乎逻辑的,但需求可能不同。我只是提出了我的想法。真的,这取决于设计的需要。你的例子足以证明代表的使用。顺便说一句,代码可能看起来比你的更长,因为你省略了大部分= D – Nayan 2010-04-14 19:31:49

+0

-1:我想你错过了将代码升级到下一级责任的代码。如果你不同意,请告诉我。 – 2011-01-04 21:36:04