带参数的单身人士

vel*_*koz 33 c# parameters singleton arguments design-patterns

我需要一个单例类来实例化一些参数.我现在这样做的方式是:

class SingletonExample
{
     private SingletonExample mInstance;
     //other members... 
     private SingletonExample()
     {

     } 
     public SingletonExample Instance
     {
         get
         {
              if (mInstance == null)
              {
                  throw new Exception("Object not created");
              }
              return mInstance;
         }
     }

     public void Create(string arg1, string arg2)
     {
         mInstance = new SingletonExample();
         mInstance.Arg1 = arg1;
         mInstance.ObjectCaller = new ObjectCaller(arg2);
         //etc... basically, create object...
     } 
}
Run Code Online (Sandbox Code Playgroud)

该实例是"迟到"创建的,这意味着我没有在app启动时获得所有必需的参数.

一般来说,我不喜欢强制方法调用的排序,但我在这里看不到另一种方式.IoC也不会解决它,因为我可以在容器中注册它,我也可以调用Create()...

你认为这是一个好的方案吗?你有其他想法吗?

编辑:我知道我写的一个例子,它不是线程安全的,线程安全不是问题的一部分

ann*_*ata 34

单身人士是丑陋的,但因为用户whateva无法纠正他自己的代码......

public class Singleton 
{ 
    private static Singleton _instance = null; 

    private static Object _mutex = new Object();

    private Singleton(object arg1, object arg2) 
    { 
        // whatever
    } 

    public static Singleton GetInstance(object arg1, object arg2)
    { 
        if (_instance == null) 
        { 
          lock (_mutex) // now I can claim some form of thread safety...
          {
              if (_instance == null) 
              { 
                  _instance = new Singleton(arg1, arg2);
              }
          } 
        }

        return _instance;
    }
}  
Run Code Online (Sandbox Code Playgroud)

Skeet在几年前的博客中写道,我认为,它非常可靠.没有必要的例外,你不会记住什么对象应该是单身,并在你弄错时处理后果.

编辑:类型不相关使用你想要的,object这里只是为了方便起见.

  • 谈论修复你的代码...神圣的废话,这是错误的.为你修好了. (3认同)

Eri*_*ler 23

一个带有参数的单身人士对我来说有点腥味.

考虑whateva的答案和以下代码:

Singleton x = Singleton.getInstance("hello", "world");
Singleton y = Singleton.getInstance("foo", "bar");
Run Code Online (Sandbox Code Playgroud)

显然,x == y和y与x的创建参数一起使用,而y的创建参数则被简单地忽略.结果可能至少令人困惑.

如果你真的,真的像你必须这样做,就这样做:

class SingletonExample
{
     private static SingletonExample mInstance;
     //other members... 
     private SingletonExample()
     {  // never used
        throw new Exception("WTF, who called this constructor?!?");
     }
     private SingletonExample(string arg1, string arg2)
     {
         mInstance.Arg1 = arg1;
         mInstance.ObjectCaller = new ObjectCaller(arg2);
         //etc... basically, create object...    
     } 
     public static SingletonExample Instance
     {
         get
         {
              if (mInstance == null)
              {
                  throw new Exception("Object not created");
              }
              return mInstance;
         }
     }

     public static void Create(string arg1, string arg2)
     {
         if (mInstance != null)
         {
             throw new Exception("Object already created");
         }
         mInstance = new SingletonExample(arg1, arg2);             
     } 
}
Run Code Online (Sandbox Code Playgroud)

在多线程环境中,添加同步以避免竞争条件.

  • Massimiliano,在我的解决方案中,您可以调用一次创建.而且我认为我的短信很清楚,我也不太喜欢参数化单例的想法. (8认同)
  • -1我不同意解决方案,因为我认为你建议使用不应该使用的单例模式.单例是一个只允许创建自身的单个实例的类,并且通常只提供对该实例的简单访问.如果所有具有相同参数的请求都应该访问相同的实例,则工厂模式是合适的.在此解决方案中你可以多次调用Create(.....)来破坏类的不变性. (7认同)

Bog*_*xim 6

更好的答案:

  1. 创建一个界面:( ISingleton包含你想做的任何动作)

  2. 而你的类型: Singleton : ISingleton

  3. 假设您有权访问UnityContainer:

IUnityContainer _singletonContainer = new UnityContainer(); // or whatever code to initialize the container

  1. 当您准备创建类型使用时(假设您使用Unity for DI):

_singletonContainer.RegisterType(typeof(ISingleton), new Singleton(params));

  1. 如果你想抓住单身人士只需使用:

var localSingletonVar = _singletonContainer.Resolve<ISingleton>();

注意:如果容器没有为ISingleton接口注册的类型,那么它应该抛出异常,或者返回null.

旧答案:

public class Singleton
{

    private static Singleton instance = null;

    private Singleton(String arg1, String arg2)
    {
    }

    public static Singleton getInstance(String arg1, String arg2)
    {
        if (instance != null)
        {
            throw new InvalidOperationException("Singleton already created - use getinstance()");
        }
        instance = new Singleton(arg1, arg2);
        return instance;
    }

    public static Singleton getInstance()
    {
        if (instance == null)
            throw new InvalidOperationException("Singleton not created - use GetInstance(arg1, arg2)");
        return instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

我会用类似的东西(你可能需要检查是否也创建了实例),或者,如果你的DI容器支持在非注册类型上抛出异常,我会继续使用它.

ATTN:非线程安全代码:)