sobota, 7 lipca 2012

[Wzorce projektowe] Strategy

Analogia z życia:

Podróżując na wakacje można zdecydować się na różne środki transportu. Ktoś woli jechać samochodem, ktoś pociągiem a ktoś inny lecieć samolotem. W każdym z tych przypadków zapłacimy za bilet inną kwotę. W przypadku samolotu płacimy za konkretne połączenie, natomiast w przypadku samochodu zapłacimy za benzynę, czyli koszt będzie zależny od ilości przejechanych kilometrów. Tak więc pomimo tego samego efektu (dotarcie do pewnego miejsca), koszty podróży wyliczone zostaną innym algorytmem.




Zastosowanie: 

Strategii używamy wszędzie tam, gdzie mamy do czynienia z pewnymi rodzinami podobnych algorytmów. Algorytmy te, dzięki wzorcowi mogą rozwijać się niezależnie od klas, które je wykorzystują. Dzięki temu uzyskujemy separację pomiędzy samym działaniem algorytmu, a przetwarzaniem wyników, jakie on zwróci. W każdym miejscu, gdzie pojawiają się wyrażenie switch, if - else i sterują one wywołaniem jakiejś metody, można zastanowić się nad zastosowaniem wzorca strategii. Dzięki temu dodanie nowego algorytmu nie spowoduje modyfikacji klasy, która z niego korzysta.

Zasada działania:

Najprościej użyć wspólnego interfejsu dla rodziny strategii, oraz konkretnych implementacji jako konkretnych algorytmów. 


Przykład implementacyjny:

    public interface ICentralElement
    {
        List<int> Collection { get; set; }
        int CalculateCentralElement();
    }
    public class AverageAlgorithm : ICentralElement
    {
        public List<int> Collection { get; set; }

        public int CalculateCentralElement()
        {
            return (int)Collection.Average();
        }
    }
    public class MedianAlgorithm : ICentralElement
    {
        public List<int> Collection { get; set; }

        public int CalculateCentralElement()
        {
            return Collection[Collection.OrderBy(s => s).ToArray().Count()/2];
        }
    }
 public class CentralElementStrategy
    {
        private readonly ICentralElement _strategy;

        public CentralElementStrategy(ICentralElement strategy)
        {
            _strategy = strategy;

        }

        public int Calculate()
        {
            return _strategy.CalculateCentralElement();
        }
    }
class Program
    {
        public static CentralElementStrategy Strategy;

        static void Main(string[] args)
        {
            RandomStrategy();

            Console.WriteLine(Strategy.Calculate());
        }

        public static void RandomStrategy()
        {
            ICentralElement centralElement;
            Random r = new Random();
            var num = r.Next();
            if (num % 2 == 0)
                centralElement = new MedianAlgorithm();
            else
                centralElement = new AverageAlgorithm();

            List<int> list = new List<int>();
            for (int i = 0; i < 20; i++)
            {
                list.Add(r.Next());
            }
            centralElement.Collection = list;

            Strategy = new CentralElementStrategy(centralElement);
        }
    }

Platforma .NET Framework udostępnia pewne mechanizmy ułatwiające implementację wzorca strategii, takie jak delegaty np. Func<>, Action<>, Predicate<> itd.

Brak komentarzy:

Prześlij komentarz