Делегаты в действии - PullRequest
       27

Делегаты в действии

0 голосов
/ 16 апреля 2010

Я учу делегатов. Мне очень любопытно применить делегатов к следующей схеме цепочки ответственности.

Пожалуйста, помогите мне как применить делегатов к следующему фрагменту.

Заранее спасибо. Спасибо за ваши усилия.

#region Chain of Responsibility Pattern
namespace Chain
{
    public class Player
    {
        public string Name { get; set; }
        public int Score { get; set; }
    }

    public abstract class PlayerHandler
    {
        protected PlayerHandler _Successor = null;

        public abstract void HandlePlayer(Player _player);

        public void SetupHandler(PlayerHandler _handler)
        {
            _Successor = _handler;
        }
    }

    public class Employee : PlayerHandler
    {
        public override void HandlePlayer(Player _player)
        {
            if (_player.Score <= 100)
            {
                MessageBox.Show(string.Format("{0} is greeted 
                                by Employee", _player.Name));
            }
            else
            {
                _Successor.HandlePlayer(_player);
            }
        }
    }

    public class Supervisor : PlayerHandler
    {
        public override void HandlePlayer(Player _player)
        {
            if (_player.Score >100 && _player.Score<=200)
            {
                MessageBox.Show(string.Format("{0} is greeted
                                by Supervisor", _player.Name));
            }
            else
            {
                _Successor.HandlePlayer(_player);
            }
        }
    }

    public class Manager : PlayerHandler
    {
        public override void HandlePlayer(Player _player)
        {
            if (_player.Score > 200)
            {
                MessageBox.Show(string.Format("{0} is
                                 greeted by Manager", _player.Name));
            }
            else
            {
                MessageBox.Show(string.Format("{0} got low score",
                                 _player.Name));
            }
        }
    }

}
#endregion

#region Main()

void Main()
{

        Chain.Player p1 = new Chain.Player();
        p1.Name = "Jon";
        p1.Score = 100;

        Chain.Player p2 = new Chain.Player();
        p2.Name = "William";
        p2.Score = 170;

        Chain.Player p3 = new Chain.Player();
        p3.Name = "Robert";
        p3.Score = 300;

        Chain.Employee emp = new Chain.Employee();
        Chain.Manager mgr = new Chain.Manager();
        Chain.Supervisor sup = new Chain.Supervisor();
        emp.SetupHandler(sup);
        sup.SetupHandler(mgr);

        emp.HandlePlayer(p1);
        emp.HandlePlayer(p2);
        emp.HandlePlayer(p3);  

}

#endregion

1 Ответ

1 голос
/ 16 апреля 2010

Рассмотрим следующий образец:

public class Player
{
    private readonly string _name;
    private readonly string _surname;
    private readonly int _score;
    private string _nickName = "";


    public Player(string name, string surname, int score)
    {
        _name = name;
        _surname = surname;
        _score = score;
    }

    public string FullName
    {
        get
        {
            if (string.IsNullOrEmpty(_nickName)) return string.Format("{0} {1}", _name, _surname);
            else return string.Format("{0} \"{1}\" {2}", _name, _nickName, _surname);
        }
    }

    public int Score
    {
        get { return _score; }
    }


    public string NickName
    {
        get { return _nickName; }
        set { _nickName = value; }
    }
}

public delegate bool PlayerHandlerDelegate(Player player);

public class HandlersChain
{
    private readonly List<PlayerHandlerDelegate> _chain = new List<PlayerHandlerDelegate>();

    public void AddHandler(PlayerHandlerDelegate handler)
    {
        _chain.Add(handler);
    }

    public void HandlePlayer(Player player)
    {
        foreach (PlayerHandlerDelegate handler in _chain)
        {
            if (handler(player)) break;
        }
    }
}




class Program
{
    static PlayerHandlerDelegate CreateHandlerDelegate(string position, int minScore)
    {
        return delegate(Player p)
                {
                    if (p.Score > minScore)
                    {
                        //MessageBox.Show(string.Format("{0} is greeted by {1}", p.FullName, position));
                        Console.WriteLine(string.Format("{0} is greeted by {1}", p.FullName, position));
                        return true;
                    }
                    return false;
                };
    }

    static void Main(string[] args)
    {
        Player p1 = new Player("John", "Smith", 100);
        Player p2 = new Player("William", "Brown", 170);
        Player p3 = new Player("Robert", "Johns", 500);

        HandlersChain chain = new HandlersChain();
        chain.AddHandler(delegate(Player p)
                            {
                                if (p.Score > 400)
                                {
                                    p.NickName = "The Hero";
                                }
                                return false;
                            });
        chain.AddHandler(CreateHandlerDelegate("Manager", 300));
        chain.AddHandler(CreateHandlerDelegate("Supervisor", 200));
        chain.AddHandler(CreateHandlerDelegate("Employee", 100));

        chain.AddHandler(delegate(Player p)
            {
                if (p.Score <= 100)
                {
                    //MessageBox.Show(string.Format("{0} got low score", p.FullName));
                    Console.WriteLine(string.Format("{0} got low score", p.FullName));
                    return true;
                }
                return false;
            });


        chain.HandlePlayer(p1);
        chain.HandlePlayer(p2);
        chain.HandlePlayer(p3);
    }
}

Я использовал консольное приложение, поэтому MessageBox был изменен на Консоль.

Здесь оригинальный дизайн был немного изменен. Теперь есть цепочечный объект, который содержит коллекцию обработчиков. Хендлеры не знают друг о друге. Цепочка называет их в порядке добавления. Каждый обработчик возвращает истину, если игрок был «полностью обработан», т.е. если не нужно вызывать другие обработчики в цепочке. Теоретически не требуется, чтобы обработчик возвращал true (то есть прекращал обработку), если он выполнил некоторую работу. Это зависит от базовой логики. Также вы можете видеть, что все «типичные» делегаты создаются специальным методом, использующим замыкание (см. http://en.wikipedia.org/wiki/Closure_(computer_science) к сожалению, ссылка с «(», кажется, не работает, если добавлена ​​как ссылка).

P.S. Я до сих пор использую VS 2005, поэтому в моем примере нет ничего такого, как лямбда. К сожалению.

...