2010-04-14 56 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