C # Цепочка ответственности с делегатами - PullRequest
6 голосов
/ 14 апреля 2010

Для моего понимания я реализовал шаблон цепочки ответственности.

//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 ]

9 голосов
/ 14 апреля 2010

Если я вас правильно понимаю ... вы можете удалить метод 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. Похоже, вы также можете использовать шаблон стратегии для этого конкретного примера.

3 голосов
/ 14 апреля 2010

Клиент с параметром complaintType выглядит как неуместный атрибут. Я предполагаю, что вы имеете в виду, что жалоба имеет тип.

Я могу ошибаться, в этом случае вы можете указать, какое поведение отсутствует Это просто выглядит как событие для меня. Каждый обработчик события будет вызываться в порядке подписки. Каждый обработчик может игнорировать уведомление на основании жалобы. Следующий обработчик вызывается до тех пор, пока свойство Handled для eventArgs имеет значение 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();
0 голосов
/ 14 апреля 2010

Это очень похоже на ответы выше, но более упорядочено. :)

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...