poniedziałek, 9 lipca 2012

[Wzorce projektowe] Decorator

Analogia z życia:

Pakiet Matlab - Simulink jest jednym z najpopularniejszych narzędzi do modelowania matematycznego w naukach inżynierskich. Klient może zamówić najtańszą podstawową wersję składającą się z Matlaba oraz podstawowych rozszerzeń Simulinka. Po jakimś czasie może pojawić się potrzeba modelowania ekonomicznego, więc klient jest zmuszony dokupić Financial Toolbox. Zatem podstawowe funkcjonalności zostaną nienaruszone, natomiast całość zostanie rozszerzona o dodatkowe możliwości. Podobnie sytuacja będzie się miała w przypadku przetwarzania obrazów, czy symulacji bioinformatycznych. Zawsze będziemy otrzymywali pewne rozszerzenie posiadanej już wersji.




Zastosowanie:

Wzorzec dekoratora umożliwia dynamiczne rozszerzanie istniejących obiektów. Umożliwia to elastyczność projektowania i staje się poważną konkurencją dla pod klas w hierarchii dziedziczenia. Czasami bowiem mamy do czynienia z zagadnieniem na tyle złożonym, że rozpatrywanie każdego podprzypadku, jako osobnej klasy dziedziczącej z klasy bazowej spowodowałoby rozrośnięcie się programu do ogromnych rozmiarów. Tu z pomocą przychodzi dekorator zapewniający dynamikę przy rozszerzaniu istniejących obiektów. Wzorzec ten może okazać się także przydatny przy rozszerzaniu klas zapieczętowanych (sealed) lub gdy mamy za zadanie rozszerzyć czyjś system, a nie chcemy go modyfikować wewnątrz.

Zasada działania:

Tworzymy pewną bazową abstrakcyjną klasę, lub interfejs, który ma być dekorowany. Konkretne implementacje w konstruktorze przyjmują jako parametr obiekt tej właśnie klasy. W metodach z interfejsu wywoływane są metody z klasy bazowej, plus to, co ma do zaoferowania dekorator. Parametr konstruktora jest zawsze dekorowany przez tworzony tym konstruktorem obiekt.

Przykład implementacyjny:

 public interface IDeveloperFunction
    {
        void Print();
    }

    public class Tester : IDeveloperFunction
    {
        public void Print()
        {
            Console.WriteLine("Tester");
        }
    }

    public class Coder : IDeveloperFunction
    {
        private IDeveloperFunction _myFunction;

        public Coder(IDeveloperFunction function)
        {
            _myFunction = function;
        }

        public void Print()
        {
            if(_myFunction != null)
                _myFunction.Print();
            Console.WriteLine("Coder");
            
        }
    }

    public class Architect : IDeveloperFunction
    {
        private IDeveloperFunction _myFunction;

        public Architect(IDeveloperFunction function)
        {
            _myFunction = function;
        }

        public void Print()
        {
            if(_myFunction != null)
                _myFunction.Print();
            Console.WriteLine("Architect");
            
        }
    }

    public class Manager : IDeveloperFunction
    {
        private IDeveloperFunction _myFunction;

        public Manager(IDeveloperFunction function)
        {
            _myFunction = function;
        }

        public void Print()
        {
            if (_myFunction != null)
                _myFunction.Print();
            Console.WriteLine("Manager");
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            IDeveloperFunction manager1 = new Manager(null);
            IDeveloperFunction manager2 = new Manager(new Architect(new Coder(new Tester())));
            Console.WriteLine("Manager 1");
            manager1.Print();
            Console.WriteLine("Manager 2");
            manager2.Print();
            Console.Read();
        }
    }

Brak komentarzy:

Prześlij komentarz