zoukankan      html  css  js  c++  java
  • 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>();

  • 相关阅读:
    Entity Framework 5.0运行.NET Framework 4.0之上在查询表达式中使用显示转换的一个问题
    How to get memcached all keys
    不同dll相同Type.FullName引发的问题
    WinDbg的cmdtree命令
    警惕缺省参数(Optional Parameters)对类型(Type)构造函数(Constructor)设计的影响
    如何解决Silverlight InitializeError #2103 Invalid or malformed application: Check manifest
    在北京拿5000.00元的工资
    分区表2
    C#操作config文件
    分区表1
  • 原文地址:https://www.cnblogs.com/philzhou/p/1974503.html
Copyright © 2011-2022 走看看