4

在查看几个项目的源代码时,我发现了一个我不太理解的模式。例如,在FubuMVCCommon Service LocatorFunc中,当静态提供程序更改时使用 a 。谁能解释使用的好处:

private static Func<IServiceLocator> currentProvider;
public static IServiceLocator Current
{
   get { return currentProvider(); }
}

public static void SetLocatorProvider(Func<IServiceLocator> newProvider)
{
   currentProvider = newProvider;
}

代替:

private static IServiceLocator current;
public static IServiceLocator Current
{
   get { return current; }
}

public static void SetLocator(IServiceLocator newInstance)
{
   current = newInstance;
}
4

4 回答 4

9

第一个模型相对于第二个模型的主要优势是所谓的“延迟初始化”。在第二个示例中,调用 SetLocator 后,您必须在内存中加载一个 IServiceLocator 实例并准备好运行。如果此类实例的创建成本很高,和/或一次与一堆其他对象一起创建(例如在应用程序启动时),那么尝试延迟对象的实际创建以减少对用户的明显延迟是一个好主意。此外,如果依赖项可能不被依赖类使用(比如它只需要用于某些操作,并且该类可以做其他不需要依赖项的事情),那么实例化一个将是一种浪费。

解决方案是提供“工厂方法”而不是实际实例。当实际需要实例时,调用工厂方法,并在使用前的最后可能时刻创建实例。这减少了前端加载时间并避免创建不需要的依赖项。

于 2011-03-02T20:44:08.883 回答
2

@KeithS 的好回答。这里要注意的另一件事是在某些实例的初始化的掩护下发生的事情。保持对故意可变对象的引用可能很棘手。

例如,FubuMVC 为每个 HTTP 请求启动一个嵌套的 StructureMap 容器,该容器将所有服务位置限定为该特定请求。如果您在该管道中运行已构建的类,您将希望使用通过 IServiceLocator 的该实例提供给您的上下文注入。

于 2011-05-30T02:59:57.120 回答
1

newProvider 的实现者有更多的灵活性。他们可以延迟加载,异步加载(然后如果在调用 func 时它没有加载,它可以有代码等待),他们可以允许它根据运行时参数等进行更改。

于 2011-03-02T20:50:34.280 回答
1

一个 func 允许做几件事

  1. 定位器的创建可以延迟到需要为止。因此它是懒惰的。
  2. 提供者对象不包含任何状态。除了在需要时返回当前定位器之外,关闭定位器不是它的责任。
  3. 当定位器在运行时重新配置或它决定需要不同的实例时,只要调用代码不存储对定位器的引用,它就可以控制定位器的生命周期。
  4. 由于定位器是由一种方法返回的,因此它具有更大的灵活性,例如创建一个线程本地定位器,因此它可以在每个线程中创建许多对象,而无需在一个全局对象中协调对象创建,这在涉及多个线程时可能成为瓶颈。

我相信设计师所做的可以给你比我更多的点,为什么抽象出“简单”的东西是个好主意,比如返回一个服务定位器的实例。

你的,阿洛伊斯克劳斯

于 2011-03-02T20:53:12.330 回答