sobota, 28 lipca 2012

[Wzorce projektowe] Service Locator

Analogia z życia:

Dzisiejsze telefony komórkowe oferuję wiele funkcjonalności. Możemy na przykład napisać wiadomość tekstową lub do kogoś zadzwonić. Z punktu widzenia użytkownika, wysłanie takiej wiadomości jest wykorzystaniem pewnej usługi. Piszemy wiadomość, podajemy numer i klikamy wyślij. To w jaki sposób wiadomość zostanie przekazana i ile za nią zapłacimy zależy między innymi od operatora sieci. Wkładając kartę SIM, możemy na starcie określić wspomniane warunki, aby później po uruchomieniu telefonu w każdej chwili korzystać z usługi w wybranej wersji.


Zastosowanie:

Wzorzec lokatora usług znajduje zastosowanie w sytuacji, gdy chcemy odseparować obiekty, od usług z których korzystają. Zwiększy to niezależność komponentów i ułatwi przyszłe wprowadzanie modyfikacji. Dodatkowo mając kilka podobnych serwisów, można wybierać któryś z nich przed uruchomieniem aplikacji przez odpowiednie ustawienia konfiguracyjne. Rozwiązanie takie wspiera testowalność.

Zasada działania:

Wprowadza się klasę lokatora usług, zawierającą statyczne pole typu HashTable z usługami. Kluczem do usługi w tablicy może być typ usługi lub podana nazwa. Dodatkowo klasa lokatora usług zawiera statyczne metody do pobrania i dodania nowego serwisu. Serwisy można dodawać na starcie aplikacji, np. w WPF czy Silverlight w metodzie OnStartup.

Przykład implementacyjny:

 public interface ILogger
    {
        void Write(string msg);
    }

    public class ConsoleLogger : ILogger
    {
        public void Write(string msg)
        {
            Console.WriteLine(msg);
        }
    }
internal class ServiceLocator
    {
        private static readonly Hashtable Services 
            = new Hashtable();

        public static void AddService<T>(T service)
        {
            Services.Add(typeof(T),service);
        }

        public static void AddService<T>(string name, T service)
        {
            Services.Add(name, service);
        }

        public static T GetService<T>()
        {
            return (T)Services[typeof(T)];
        }

        public static T GetService<T>(string name)
        {
            return (T)Services[name];
        }

    }
public class Fibonnaci
    {
        public int Number { get; set; }
        public int LastNum { get; set; }

        public Fibonnaci()
        {
            LastNum = 0;
            Number = 1;
        }

        public int Next()
        {
            var n = LastNum + Number;
            LastNum = Number;
            Number = n;
            IsDivisibleBy4();
            return n;
        }

        public void IsDivisibleBy4()
        {
            if (Number%4 != 0) return;
            var logger = ServiceLocator.GetService<ILogger>();
            logger.Write(String.Format
                             ("Number {0}, last : {1}",Number, LastNum));
        }
    }
class Program
    {
        static Program()
        {
            ServiceLocator.AddService<ILogger>(new ConsoleLogger());
        }

        static void Main(string[] args)
        {
            Fibonnaci fibonnaci = new Fibonnaci();
            for (int i = 0; i < 100; i++)
            {
                fibonnaci.Next();
            }
            Console.ReadKey();
        }
    }

Brak komentarzy:

Prześlij komentarz