什么是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 Fieldsprivate 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 : classwhere 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();}}
}

本文转自匠心十年博客园博客,原文链接:http://www.cnblogs.com/gaochundong/archive/2013/04/12/service_locator_pattern.html,如需转载请自行联系原作者

Service Locator 模式相关推荐

  1. (转载)Service Locator模式(简单的IOC容器实现 MVVMLight SimpleIoc)

    转载自:https://www.cnblogs.com/gaochundong/archive/2013/04/12/service_locator_pattern.html 什么是Service L ...

  2. 设计模式 - 服务定位模式 Service Locator Pattern

    译者序:看 spring framework 时候了解到的 Service Locator 模式,顺便搜到了这篇文章,感觉很棒,顺手翻译下,好安利给其他小伙伴. 原文链接:http://gamepro ...

  3. 三十六、服务定位器模式 (Service Locator Pattern)

    服务定位器模式(Service Locator Pattern)用于想使用 JNDI 查询定位各种服务的时候 考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术 在首次请求某 ...

  4. php service locator,服务定位器模式(Service Locator)

    服务定位器模式(Service Locator) 服务定位器模式被一些人认为是一种反面模式.它违反了依赖倒置原则.该模式隐藏类的依赖,而不是暴露依赖(如果暴露可通过依赖注入的方式注入依赖).当某项服务 ...

  5. 设计模式のService Locator Pattern

    Service Locator Pattern 学习 spring 的时候遇到的一个设计模式. 关于此设计模式的geeksforgeeks的原文 ,我理解性的翻译了下,添加了些自己的理解. 用 抽象层 ...

  6. Service Locator服务定位器

    先讲服务定位器, 有些摘录于 http://www.digpage.com/convention.html Service Locator目的也在于解耦他的模式非常贴合Web这种基于服务和组件的应用的 ...

  7. php service locator,Yii源码解读-服务定位器(ServiceLocator)

    SL的目的也是解耦,并且非常适合基于服务和组件的应用. Service Locator充当了一个运行时的链接器的角色,可以在运行时动态地修改一个类所要选用的服务, 而不必对类作任何的修改. 一个类可以 ...

  8. Design Pattern - Service Locator Pattern--转载

    原文地址:http://www.tutorialspoint.com/design_pattern/service_locator_pattern.htm The service locator de ...

  9. Service Locator Pattern in C# with Lazy Initialization(转)

    原文 In my previous post Service Locator Pattern in C#: A Simple Example I introduced a fairly basic i ...

最新文章

  1. android文件的读取方法,Android读取写入文件的方法
  2. oracle /+append/好用吗,ORACLE-insert /*+append*/提高性能
  3. Nginx 负载均衡4种模式
  4. 从蓝桥杯来谈Fibonacci数列
  5. 中国程序员,请挺起你的腰杆!
  6. IOC操作Bean管理XML方式(有参构造注入属性)
  7. 【实践驱动开发2-001】wifi 在android 下的实现 - AR6000 系列移植详细步骤
  8. matlab设计凸轮轮廓代码_机械设计基础之什么是凸轮机构,分类和常用运动规律是怎么样的?...
  9. Java实现redis管道
  10. hdu Hero 4310 贪心水果 多校联合赛(二)第一题
  11. 暗黑破坏神3 夺魂之镰曝光“威斯特玛”城背景
  12. 音乐app、app原型、音乐原型、云音乐、听歌、电台、本地音乐、点赞、收藏、歌单广场、动态、社区、评论、歌词、歌手、主播、视频、云村、下载、翻唱、歌曲播放、订阅、频道、引导页、登录注册、axure原型
  13. [LiteratureReview]A survey of image semantics-based visual simultaneous localization and mapping....
  14. 关于维基百科你不知道的十件事:
  15. DCC:Deep continuous clustering
  16. hcia是什么等级的证书_HCIA是什么等级的证书
  17. k8s每天报告服务器状态信息,[工作随笔] 配置 cron 检查 K8s Pod 存活状态以推送钉钉消息...
  18. 用html写qq音乐,html+caa手写qq音乐
  19. oracle leg,[LEG引擎]英雄合击数据库
  20. 2021高考 海南中学成绩查询,2021海南省地区高考成绩排名查询,海南省高考各高中成绩喜报榜单...

热门文章

  1. 12款国内外企业协作工具推荐
  2. STM32使用keil串口输出中文乱码问题
  3. python双色球模拟投注及开奖,可复式投注
  4. turtle_如何绘制菱形
  5. 会打麻将的人工智能来了
  6. Python交通标志识别基于卷积神经网络的保姆级教程(Tensorflow)
  7. Windows网络服务渗透测试实战MS17-010漏洞复现
  8. mysql使用许可_MySQL授权许可解析
  9. 使用开源软件vlc media player 录制桌面视频
  10. 九十年代计算机及应用,全国计算机等级考试历史发展