ServiceLocator Design Pattern

Design pattern'leri spagetti kodlara veya tekrar eden kod bloklarına çözümler olarak ortaya çıkmışlardır. ServiceLocator design pattern ile bağımsız bir şekilde geliştirilebilen, test edilebilen loosely coupled modüller inşa edebilirsiniz. 

ServiceLocator'ı kısaca tanımlamak gerekirse projede kullanılan service instance'larını tek bir yerden add ve get yönetimini yapma işlemlerinden sorumludur diyebiliriz.

İmplemente ederken bağımlılığı interface ve propertilerden veya constructor seviyesinde inject edilebilirsiniz.

Örnek verecek olursak birden fazla service instance'ınızın bulunduğu bir proje var ve bir ara katman web service projesi ile bu servislerin metotlarını dışarıya açtınız diyelim. Her bir metot call işleminde service instance oluşturmak yerine app-start veya başka bir anda instance'ları ServiceLocator'a register edip sonrasında ihtiyaç duyulan yerlerde burada bulunan instance'lar üzerinden service'leri kullanmak diyebiliriz.

ServiceLocator'ın temel yapı taşlarını aşağıdaki gibi sıralayabiliriz;

  1. ServiceLocator , İhtiyaç duyulan service instance'ının yaratılmasından sorumludur, eğer yaratılmışsa da serviceRepository görevi görür diyebiliriz,
  2. Initializer ,  Runtime'da service instance'ının yaratılmasından sorumludur. Instance bir kere oluşturulduğunda ServiceLocator içerisinde store edilir,
  3. Client , Service consumer'larını veya service client'larını temsil eder,
  4. Service(s) , Service contract'larını ve onların implementasyonunu temsil eder.

 

ServiceLocator Patter'nin Implementasyonu

İlk olarak VS kullanarak bir tane WCF projesi oluşturalım ve sonrasında CustomerService ve ProductService adında 2 tane service oluşturalım. Bu iki service'in contract interface'leride aşağıdaki gibi tanımlayalım.

        [ServiceContract]
        public interface ICustomerService
        {
            [OperationContract]
            string GetName();
        }

        [ServiceContract]
        public interface IProductService
        {
            [OperationContract]
            string GetName();
        }

Sırada bu contract'ları service'lere implement etme var.

        public class ProductService : IProductService
        {
            public string GetName()
            {
                return "Fitbit";
            }
        }

        public class CustomerService : ICustomerService
        {
            public string GetName()
            {
                return "John travolta";
            }
        }

Şimdi ise sırada ServiceLocator class'ını yaratmak var. Bu class static olacak ve içerisinde service instance'larını tutan bir Dictionary bulunduracak. Bu Dictionary için get ve set operasyonları kullanılmak üzre ServiceLocator class içerisinde RegisterService ve GetService adında 2 adet metot tanımlayacağız. RegisterService instance'ları dictionary'e eklemek için kullanacağımız metot. GetService ise dictionary'de bulunan service instance'ını return eden metot olacak.

    public static class ServiceLocator
    {
        private static readonly Dictionary<Type, object> registeredServices = new Dictionary<Type, object>();

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

        public static void RegisterService<T>(T service)
        {
            registeredServices[typeof(T)] = service;
        }

        public static int Count
        {
            get { return registeredServices.Count; }
        }
    }

Bu aşamaya kadar oldukça basit bir ServiceLocator pattern ile projemizi oluşturduk. Şimdi ise sırada oluşturduğumuz bu Locator'ı proje içerisinde kullanmak var.

    static void Main(string[] args)
       {
           ICustomerService customerService = new CustomerService();//service instance aldık

           IProductService productService = new ProductService();//service instance aldık

           ServiceLocator.RegisterService(customerService);//service locator'da bulunan dictionary içerisine attık

           ServiceLocator.RegisterService(productService);//service locator'da bulunan dictionary içerisine attık

           ICustomerService customerClientService = ServiceLocator.GetService<ICustomerService>();//dictionary içerisinde bulunan service instance'ını aldık

           string msg = customerClientService.GetName();

           Console.WriteLine(msg);
       }

 

ServiceLocator pattern'i objelerinizi bağımlılıklarından ayırmak istediğinizde veya compile-time'da bağımlılıkları bilinmeyen objeler oluşturmanız gerektiğinde güzel bir seçenek olabilir. 

Add comment