• A Singleton Service Locator Pattern(转)


    原文

    This is the third post of a series on the Service Locator pattern. In the first post I described how to create a basic service locator for your C# application, while in the second post I introduced lazy initialization of the services.

    We now add another piece to our puzzle, transforming the Service Locator class into a singleton.

    The Singleton Pattern

    The singleton is arguably the most known and controversial design pattern. Some say singletons are good, some says singletons are evil. Eric Gamma himself (one of the Gang Of Four) in a recent interview stated that (emphasis added):

    When discussing which patterns to drop, we found that we still love them all. (Not really—I’m in favor of dropping Singleton. Its use is almost always a design smell.)

    I don’t have a strong opinion either way; I tend to use it sparingly and in the following code I will show how to apply this pattern to the service locator. There are already countless blogs discussing the pros and the cons of the singleton pattern, therefore I won’t discuss about it any further.

    The Singleton Service Locator

    The following was our initial implementation (other details of the classes have been removed for clarity). The constructor was internal, allowing all potential clients from within the assembly to invoke it. Clients could either pass around a reference to the created service locator, or instantiate new instances each time:

    internal class ServiceLocator : IServiceLocator
    {
        // a map between contracts -> concrete implementation classes
        private IDictionary<Type, Type> servicesType;
    
        // a map containing references to concrete implementation already instantiated
        // (the service locator uses lazy instantiation).
        private IDictionary<Type, object> instantiatedServices;
    
        internal ServiceLocator()
        {
            this.servicesType = new Dictionary<Type, Type>();
            this.instantiatedServices = new Dictionary<Type, object>();
    
            this.BuildServiceTypesMap();
        }
    
        // rest of the methods
     }
    

    To implement the singleton pattern, we make the constructor private and provide clients with a static method through which we can retrieve an instance of the service.

    Note how the creation of the single instance of the ServiceLocator class is itself lazy and thread safe. There are a few variations on the theme when it comes to singleton thread safe initialization (see for example this post by Jon Skeet).

    internal class ServiceLocator : IServiceLocator
    {
            // a map between contracts -> concrete implementation classes
            private IDictionary<Type, Type> servicesType;
            private static readonly object TheLock = new Object();
    
            private static IServiceLocator instance;
    
            // a map containing references to concrete implementation already instantiated
            // (the service locator uses lazy instantiation).
            private readonly IDictionary<Type, object> instantiatedServices;
    
            private ServiceLocator()
            {
                this.servicesType = new Dictionary<Type, Type>();
                this.instantiatedServices = new Dictionary<Type, object>();
    
                this.BuildServiceTypesMap();
            }
    
            public static IServiceLocator Instance
            {
                get
                {
                    lock (TheLock) // thread safety
                    {
                        if (instance == null)
                        {
                            instance = new ServiceLocator();
                        }
                    }
    
                    return instance;
                }
            }
    
            // rest of the methods
     }
    

    Clients will now simply invoke the GetService() method through the singleton instance, without having to create a new object each time:

    IServiceA service = ServiceLocator.Instance.GetService<IUniverseFileServiceAdapter>();

  • 相关阅读:
    前端学HTTP之重定向和负载均衡
    前端学HTTP之Web主机托管
    前端学HTTP之内容协商
    前端学HTTP之字符集
    前端学HTTP之实体和编码
    前端学HTTP之安全HTTP
    前端学HTTP之摘要认证
    前端学HTTP之基本认证
    前端学HTTP之客户端识别和cookie
    前端学HTTP之网关、隧道和中继
  • 原文地址:https://www.cnblogs.com/philzhou/p/1974503.html
Copyright © 2020-2023  润新知