好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Service Locator 模式

Service Locator 模式

Service Locator 模式

什么是Service Locator 模式?

服务定位模式(Service Locator Pattern)是一种软件开发中的设计模式,通过应用强大的抽象层,可对涉及尝试获取一个服务的过程进行封装。该模式使用一个称为"Service Locator"的中心注册表来处理请求并返回处理特定任务所需的必要信息。

场景描述

某类ClassA依赖于服务ServiceA和服务ServiceB,服务的具体类型需在编译时指定。

这种条件下有以下缺点:

尝试替换或更新依赖项,必须更改类的源代码并且重新编译。 依赖项的具体实现必须在编译时可用。 测试该类非常困难,因为类对依赖项有直接的引用,则依赖项不能使用Stub或Mock对象替换。 该类包含用于创建、定位和管理依赖项的重复代码。

设计目标

使用 Service Locator Pattern 来达成以下目标:

把类与依赖项解耦,从而使这些依赖项可被替换或者更新。 类在编译时并不知道依赖项的具体实现。 类的隔离性和可测试性非常好。 类无需负责依赖项的创建、定位和管理逻辑。 通过将应用程序分解为松耦合的模块,达成模块间的无依赖开发、测试、版本控制和部署。

解决方案

创建一个 Service Locator,其包含各服务的引用,并且封装了定位服务的逻辑。在类中使用 Service Locator 来获取所需服务的实例。

Service Locator 模式并不描述如何实例化服务,其描述了一种注册和定位服务的方式。通常情况下,Service Locator 模式与工厂模式(Factory Pattern)和依赖注入模式(Dependency Injection Pattern)等结合使用。

服务定位器应该能够在不知道抽象类的具体类型的情况下定位到服务。例如,它可能会使用字符串或服务接口类型来影射服务,这允许在无需修改类的条件下替换依赖项的具体实现。

实现细节

通常 ServiceLocator 类提供 IServiceLocator 接口的实现单例,并负责管理该实例的创建和访问。ServiceLocator 类提供 IServiceLocator 接口的默认实现,例如 ActivatingServiceLocator 类,可以同时创建和定位服务。

注意事项

在使用 Service Locator 模式之前,请考虑以下几点:

有很多程序中的元素需要管理。 在使用之前必须编写额外的代码将服务的引用添加到服务定位器。 类将对服务定位器有依赖关系。 源代码变的更加复杂和难以理解。 可以使用配置数据来定义运行时的关系。 必须提供服务的实现。因为服务定位器模式将服务消费者与服务提供者解耦,它可能需要提供额外的逻辑。这种逻辑将保证在服务消费者尝试定位服务之前,服务提供者已被安装和注册。

相关模式

依赖注入( Dependency Injection )。这种模式解决了与 Service Locator 模式相同的问题,但它使用不同的方法。 控制反转(Inversion of Control)。Service Locator 模式是这种模式的特殊版本。它将应用程序的传统控制流程反转。它用被调用对象来代替控制过程的调用方。

参考信息

Inversion of Control and the Dependency Injection pattern  on Martin Fowler's Web site Service Locator  on MSDN

代码示例

Service Locator 的简单实现,使用静态类实现,未使用Singleton设计,仅作Mapping影射。

 using   System;
  using   System.Collections.Generic;
  using   System.Globalization;
  using   System.Reflection;

  namespace   Infrastructure
{
    ///   <summary> 
   ///   服务定位器
    ///   </summary> 
   public   static   class   ServiceLocator
  {
      #region  Fields

     private   static   readonly  Dictionary<Type, Type> _mapping =  new  Dictionary<Type, Type> ();
      private   static   readonly  Dictionary<Type,  object > _resources =  new  Dictionary<Type,  object > ();
      private   static   object  _operationLock =  new   object  ();

      #endregion 

     #region  Add

     ///   <summary> 
     ///   添加注册资源
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     ///   <param name="instance">  资源实例  </param> 
     public   static   void  Add<TClass>( object   instance)
          where  TClass :  class  
    {
      Add(  typeof  (TClass), instance);
    }

      ///   <summary> 
     ///   添加注册资源
      ///   </summary> 
     ///   <param name="typeOfInstance">  资源类型  </param> 
     ///   <param name="instance">  资源实例  </param> 
     public   static   void  Add(Type typeOfInstance,  object   instance)
    {
        if  (typeOfInstance ==  null  )
          throw   new  ArgumentNullException( "  typeOfInstance  "  );
        if  (instance ==  null  )
          throw   new  ArgumentNullException( "  instance  "  );

        if  (! (typeOfInstance.IsInstanceOfType(instance)))
      {
          throw   new   InvalidCastException(
              string  .Format(CultureInfo.InvariantCulture,
              "  Resource does not implement supplied interface: {0}  "  , typeOfInstance.FullName));
      }

        lock   (_operationLock)
      {
          if   (_resources.ContainsKey(typeOfInstance))
        {
            throw   new   ArgumentException(
                string .Format(CultureInfo.InvariantCulture,  "  Resource is already existing : {0}  "  , typeOfInstance.FullName));
        }
        _resources[typeOfInstance]  =  instance;
      }
    }

      #endregion 

     #region  Get

     ///   <summary> 
     ///   查找指定类型的资源实例
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     ///   <returns>  资源实例  </returns> 
     public   static  TClass Get<TClass> ()
          where  TClass :  class  
    {
        return  Get( typeof (TClass))  as   TClass;
    }

      ///   <summary> 
     ///   查找指定类型的资源实例
      ///   </summary> 
     ///   <param name="typeOfInstance">  The type of instance.  </param> 
     ///   <returns>  资源实例  </returns> 
     public   static   object   Get(Type typeOfInstance)
    {
        if  (typeOfInstance ==  null  )
          throw   new  ArgumentNullException( "  typeOfInstance  "  );

        object   resource;

        lock   (_operationLock)
      {
          if  (!_resources.TryGetValue(typeOfInstance,  out   resource))
        {
            throw   new   ResourceNotFoundException(typeOfInstance.FullName);
        }
      }

        if  (resource ==  null  )
      {
          throw   new   ResourceNotInstantiatedException(typeOfInstance.FullName);
      }

        return   resource;
    }

      ///   <summary> 
     ///   尝试查找指定类型的资源实例
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     ///   <param name="resource">  资源实例  </param> 
     ///   <returns>  是否存在指定资源类型的资源实例  </returns> 
     public   static   bool  TryGet<TClass>( out   TClass resource)
          where  TClass :  class  
    {
        bool  isFound =  false  ;

      resource  =  null  ;
        object   target;

        lock   (_operationLock)
      {
          if  (_resources.TryGetValue( typeof (TClass),  out   target))
        {
          resource  = target  as   TClass;
          isFound  =  true  ;
        }
      }

        return   isFound;
    }

      #endregion 

     #region  Register

     ///   <summary> 
     ///   注册类型
      ///   </summary> 
     ///   <typeparam name="TClass">  实体类型,类型限制为有公共无参构造函数  </typeparam> 
     public   static   void  RegisterType<TClass> ()
        where  TClass :  class ,  new  ()
    {
        lock   (_operationLock)
      {
        _mapping[  typeof (TClass)] =  typeof  (TClass);
      }
    }

      ///   <summary> 
     ///   注册类型
      ///   </summary> 
     ///   <typeparam name="TFrom">  资源类型  </typeparam> 
     ///   <typeparam name="TTo">  实体类型,类型限制为有公共无参构造函数  </typeparam> 
     public   static   void  RegisterType<TFrom, TTo> ()
        where  TFrom :  class 
       where  TTo : TFrom,  new  ()
    {
        lock   (_operationLock)
      {
        _mapping[  typeof (TFrom)] =  typeof  (TTo);
        _mapping[  typeof (TTo)] =  typeof  (TTo);
      }
    }

      ///   <summary> 
     ///   是否已注册此类型
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     ///   <returns>  是否已注册此类型  </returns> 
     public   static   bool  IsRegistered<TClass> ()
    {
        lock   (_operationLock)
      {
          return  _mapping.ContainsKey( typeof  (TClass));
      }
    }

      #endregion 

     #region  Resolve

     ///   <summary> 
     ///   获取类型实例
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     ///   <returns>  类型实例  </returns> 
     public   static  TClass Resolve<TClass> ()
        where  TClass :  class  
    {
      TClass resource  =  default  (TClass);

        bool  existing = TryGet<TClass>( out   resource);
        if  (! existing)
      {
        ConstructorInfo constructor  =  null  ;

          lock   (_operationLock)
        {
            if  (!_mapping.ContainsKey( typeof  (TClass)))
          {
              throw   new   ResourceNotResolvedException(
                string .Format(CultureInfo.InvariantCulture,  "  Cannot find the target type : {0}  " ,  typeof  (TClass).FullName));
          }

          Type concrete  = _mapping[ typeof  (TClass)];
          constructor  = concrete.GetConstructor(BindingFlags.Instance | BindingFlags.Public,  null ,  new  Type[ 0 ],  null  );
            if  (constructor ==  null  )
          {
              throw   new   ResourceNotResolvedException(
                string .Format(CultureInfo.InvariantCulture,  "  Public constructor is missing for type : {0}  " ,  typeof  (TClass).FullName));
          }
        }

        Add <TClass>((TClass)constructor.Invoke( null  ));
      }

        return  Get<TClass> ();
    }

      #endregion 

     #region  Remove

     ///   <summary> 
     ///   移除指定类型的资源实例
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     public   static   void  Remove<TClass> ()
    {
      Teardown(  typeof  (TClass));
    }

      ///   <summary> 
     ///   移除指定类型的资源实例
      ///   </summary> 
     ///   <param name="typeOfInstance">  资源类型  </param> 
     public   static   void   Remove(Type typeOfInstance)
    {
        if  (typeOfInstance ==  null  )
          throw   new  ArgumentNullException( "  typeOfInstance  "  );

        lock   (_operationLock)
      {
        _resources.Remove(typeOfInstance);
      }
    }

      #endregion 

     #region  Teardown

     ///   <summary> 
     ///   拆除指定类型的资源实例及注册映射类型
      ///   </summary> 
     ///   <typeparam name="TClass">  资源类型  </typeparam> 
     public   static   void  Teardown<TClass> ()
    {
      Teardown(  typeof  (TClass));
    }

      ///   <summary> 
     ///   拆除指定类型的资源实例及注册映射类型
      ///   </summary> 
     ///   <param name="typeOfInstance">  资源类型  </param> 
     public   static   void   Teardown(Type typeOfInstance)
    {
        if  (typeOfInstance ==  null  )
          throw   new  ArgumentNullException( "  typeOfInstance  "  );

        lock   (_operationLock)
      {
        _resources.Remove(typeOfInstance);
        _mapping.Remove(typeOfInstance);
      }
    }

      #endregion 

     #region  Clear

     ///   <summary> 
     ///   移除所有资源
      ///   </summary> 
     public   static   void   Clear()
    {
        lock   (_operationLock)
      {
        _resources.Clear();
        _mapping.Clear();
      }
    }

      #endregion  
  }
} 

Service Locator 测试代码

 using   System;
  using   Infrastructure;

  namespace   ServiceLocatorTest
{
    class   Program
  {
      interface   IServiceA
    {
        string   GetData();
    }

      class   ServiceA : IServiceA
    {
        public   string   GetData()
      {
          return   "  This data is from ServiceA  "  ;
      }
    }

      static   void  Main( string  [] args)
    {
      ServiceLocator.RegisterType <IServiceA, ServiceA> ();
      IServiceA serviceA  = ServiceLocator.Resolve<IServiceA> ();
        string  data =  serviceA.GetData();
      Console.WriteLine(data);
      Console.ReadKey();
    }
  }
} 

 

 

 

标签:  Dependency Injection ,  Inversion of Control ,  Service Locator

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Service Locator 模式的详细内容...

  阅读:37次