具有公共(单实例)构造函数的单例

时间:2008-12-21 16:05:50

标签: c# design-patterns

作为一个练习,我正在将我们庞大且经过强悍处理的Delphi框架的一部分翻译成C#。

此框架中包含一个通用的单例父类。当然,在C#中实现单例是相当容易的(甚至有一篇Jon Skeet文章,所以我还希望如此),但我们的Delphi单例对模式的看法略有不同:与发布'实例'相反property / method,它有一个“伪”构造函数,它总是返回相同的实例。这种方法的基本特征是单身类的用户不知道他正在处理单身人员: 据他们所知,他们只是构建任何旧类并从中请求一些信息。

我想在C#中完成同样的事情(作为一个练习,所以它不一定是生产质量的代码,邪恶的hackery很好),但到目前为止,我已经失败了。

任何建议让一个简单的myInstance = new MyClass();总是返回相同的实例是非常受欢迎的!


其他信息

  • 我们正在谈论框架提供的单例模式的便利实现。它不一定必须是父类,但它也必须帮助开发人员创建自己的单例。要求他们手动将所有方法调用重定向到单实例,不会让他们满心欢喜。 : - )

  • 我真的不想讨论这是否是处理单身人士的正确方法,因为现在我只对c#-tweaking的精细艺术感兴趣。

7 个答案:

答案 0 :(得分:7)

你会做一个代理(编辑:正如汤姆在下面指出的那样,正确的设计模式是Monostate):

public class MyClass {
  MyActualClass _actual;
  public MyClass() {
    _actual = MyActualClass. Instance;
  }
  public DoStuff() {
    _actual.DoStuff();
  }
}

internal class MyActualClass {
  private MyActualClass {
  }
  public DoStuff() {
    ...
  }
  MyActualClass _instance;
  public static Instance {
    get {
       if(_instance == null)
         _instance = new MyActualClass()
       return _instance;
    }
  }
}

...

public static void Main() {
  var my1 = new MyClass();
  var my2 = new MyClass();   
}

my1!= my2但my1.DoStuff()调用与my2.DoStuff()相同的方法实例 如果您只编程了一个接口,这将进一步简化。

编辑:通过使_actual保护内部并覆盖MyClass.Equals(object obj)以检查this._actual == obj._actual

,可以部分解决相等问题

答案 1 :(得分:4)

我相信Monostate模式可以满足您的需求:

Monostate为我们提供了我们在Singleton中如此珍惜的状态的奇点,但没有伴随它的所有静态头痛。”

更多信息: http://jeremyjarrell.com/archive/2008/04/21/88.aspx

答案 2 :(得分:2)

据我所知,由于C#如何处理对象实例,因此无法实现。为了调用构造函数,必须实际创建实例,并且不能只是从构造函数“返回”另一个对象。

我能想出的最好的东西(除了使用工厂方法)是将类内部视为Singleton,并创建“虚拟”实例,这些实例在创建时只指向原始实例。因此,例如,在构造函数中,您将检查单例是否已初始化,如果没有,将初始化它,那么您基本上只需将每个实例的方法和属性代理回单例。

在这个实现中,单例不一定必须是同一个类,但如果你想保持包含,你可以。

更新:这种方法的一个缺点是虽然每个实例都表现为作为单身,但它仍然有自己的对象引用,因此您可能也想要覆盖Equals()进行相等比较。

答案 3 :(得分:0)

我不知道你怎么做,因为构造函数不使用return语句。你可以克隆到单例的所有相关链接,但它会有本地变量的本地副本,并且非常混乱。

而是让构造函数检查单例是否已实例化,如果已经实例化,则抛出异常,或者向使用旧样式代码的开发人员发出警告。

答案 4 :(得分:0)

我认为你可能会用Remoting推出一些东西。

<强>更新

更好的方法是在结构或轻量级类中包装一个合适的单例类。

答案 5 :(得分:0)

将单例创建为静态成员,并使所有方法访问单个静态实例。

class SingletonWrapper {

    private static RealSingleton instance = new RealSingleton();

    public void methodA() {
        instance.methodA();
    }

    public String getA() {
        return instance.getA();
    }

}

(这实际上是Java代码,但我认为C#足够相似了。)

答案 6 :(得分:0)

如何使用静态函数返回对象而不是使用new关键字。

static private m_obj my_obj;
static private bool my_new_obj;
static public m_obj create_m_obj()
{
    if (my_new_obj == false)
    {
        my_new_obj = true;
        my_obj = new my_obj();
    }
    return my_obj;
}

如果我没有弄错的话,你可以轻松完全控制对象的创建。