ServiceLocator 实现

365不给提款流水数据异常 📅 2025-08-25 22:41:41 👤 admin 👁️ 7875 ❤️ 865
ServiceLocator 实现

当我第一次看到ServiceLocator这个名字的时候以为只是一个常见的类名而已,后来才知道这其实是一种设计模式。ServiceLocator 充当了一个中介的角色,负责定位和提供服务的实例。它最终目的是为了解决依赖管理的问题。

ServiceLocator 实现一个简单的例子:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657public interface IService{ void Execute();}public class ServiceA : IService{ public void Execute() { Console.WriteLine("Service A is executing."); }}public class ServiceB : IService{ public void Execute() { Console.WriteLine("Service B is executing."); }}public class ServiceLocator{ private static Dictionary services = new Dictionary(); public static void RegisterService(string key, IService service) { services[key] = service; } public static IService GetService(string key) { if (services.ContainsKey(key)) { return services[key]; } throw new KeyNotFoundException($"Service with key '{key}' is not registered."); }}public class Program{ public static void Main(string[] args) { // 注册服务 ServiceLocator.RegisterService("ServiceA", new ServiceA()); ServiceLocator.RegisterService("ServiceB", new ServiceB()); // 获取并使用服务 IService serviceA = ServiceLocator.GetService("ServiceA"); serviceA.Execute(); IService serviceB = ServiceLocator.GetService("ServiceB"); serviceB.Execute(); }}

ServiceLocator 就做了一件事:负责提供服务的实例。

为什么需要 ServiceLocator?当我们还是小白,没有任何设计模式的概念时,代码应该是这样写的:

1234567891011121314151617181920public class ServiceA{ public void Execute() { Console.WriteLine("Service A is executing."); }}public class ServiceB{ public void Execute() { var serviceA = new ServiceA(); serviceA.Execute(); Console.WriteLine("Service B is executing."); }}var serviceA = new ServiceB();serviceA.Execute();

显然,ServiceA 依赖于 ServiceB 的实现,这违反了依赖倒置原则。于是我们引入了接口:

123456789101112131415161718192021222324public interface IServiceA{ void Execute();}public class ServiceA : IServiceA{ public void Execute() { Console.WriteLine("Service A is executing."); }}public class ServiceB{ public void Execute(IServiceA serviceA) { serviceA.Execute(); Console.WriteLine("Service B is executing."); }}var serviceB = new ServiceB();serviceB.Execute(new ServiceA()); // 注入依赖参数,术语称为 "依赖注入"

现在符合了依赖倒置原则,即:抽象不应该依赖于细节,细节应该依赖于抽象。为什么需要服务定位器?当我们频繁使用依赖注入时,实际上在注入上下文中也产生了依赖:

12345678public class Foo{ public void Bar() { var serviceB = new ServiceB(); serviceB.Execute(new ServiceA()); }}

此时虽然 ServiceB 不依赖 ServiceA,但是 Foo 却和 ServiceA、ServiceB 耦合了。此时就需要 ServiceLocator 登场了。通过使用 ServiceLocator,应用程序的各个部分可以统一通过服务定位器获取它们所需的服务,而无需直接依赖于具体的实现类。这有助于减少类之间的直接依赖,提高灵活性和可维护性。采用 ServiceLocator 后的代码:

12345678public class Foo{ public void Bar() { var serviceB = ServiceLocator.GetService(); serviceB.Execute(ServiceLocator.GetService()); }}

Common Service LocatorCommonServiceLocator 是一个服务定位器的通用实现。相较于普通的服务定位器,CommonServiceLocator的区别在于它是全局唯一的服务定位器,通过设置全局的 ServiceLocator 提供者,可以在整个应用程序中使用同一个 ServiceLocator 来解析服务,而不需要每个地方都创建一个新的服务定位器实例。以 Unity 容器为例:

1234567891011using CommonServiceLocator;using Unity;using Unity.ServiceLocation;var container = new UnityContainer();container.RegisterType();var locator = new UnityServiceLocator(container);ServiceLocator.SetLocatorProvider(() => locator);var obj = ServiceLocator.Current.GetInstance();

服务定位器会隐藏具体的容器,使得调用者依赖定位器而不是容器。除了 Unity 外,一些主流的容器都有对应的 CommonServiceLocator 包装。

参考Service Locator Pattern in C#Common Service LocatorService Locator is an Anti-PatternDependency Injection vs Service LocationWhat’s the difference between the Dependency Injection and Service Locator patterns?

相关推荐

教你几招避免“远光狗”的危害
365bet娱乐场

教你几招避免“远光狗”的危害

📅 08-10 👁️ 544
三星 Galaxy S7
bte365娱乐场

三星 Galaxy S7

📅 07-10 👁️ 430