如何在不使用静态方法的情况下实现单例?

时间:2014-12-09 09:40:48

标签: design-patterns

通常,单例模式是通过使用静态方法创建一个类来实现的,该方法如果不存在,则创建该类的新实例。如果实例已存在,则只返回对该对象的引用。为了确保无法以任何其他方式实例化对象,构造函数将变为私有。有没有其他方法可以创建单身人士?

2 个答案:

答案 0 :(得分:1)

静态公共只读变量

(如果您的语言支持)

C#:

public static readonly MyClass singleton = new MyClass(); // create at class/assembly load/access

的Java:

public static final MyClass singleton;

static {
    singleton = new MyClass();
}

C ++:

// header
class MyClass {
public:
   static MyClass singleton; // value, created before main, or at dll load
   static MyClass const * singleton; // const ptr to non-const value, created before main 
private:
   MyClass();
   ~MyClass();
   MyClass(const Myclass&) = delete; // c++11, remove default implementation  
}

// in cpp:
MyClass Myclass::singleton;
MyClass const* MyClass::singleton = new MyClsas;

对于大多数编译器/语言,这可以避免需要线程锁定和初始化/销毁顺序问题的按需创建问题。

通过main()或依赖注入

显式显示

然而,我做单例的首选方法是在某处创建一个字段/属性并显式初始化(​​在main中或通过一些依赖注入框架。这对管理许多单例类型有很大帮助,特别是对于测试。

如果你愿意,你可以另外测试并阻止设置singleton属性设置多次,至少在没有运行测试时。

 int main()
 {
      // Just set it. Use discipline to prevent others
      MyClass.singleton = new MyClass();

      // Use function, then we can enforce set-only-once, if required
      MyClass.setSingleton(new MyClass());          

      // dependency injection via env-vars! :)
      MyClass::setSingleton(ClassFactory::create(getenv("MYCLASS_SINGLETON_TYPE"));

      mainLoop();
 } 

将单身人士存放在其他地方

拥有“管理员”或“注册表”或其他任何东西以保存所有全局对象通常很方便。然后该类可以负责创建/设置所需的所有大型单例对象。

这样,您用作单身人士的班级不需要关心单身人士。在测试或“重置”样式场景时非常有用。

它还有助于将所有这些“大”对象集中在某处,以便可以在一个地方找到并管理全局状态,而不是在整个应用程序中找到5-25个不同的类。

答案 1 :(得分:0)

您可以在方法中同步称为双重检查锁定的最常见模式。

http://en.wikipedia.org/wiki/Double-checked_locking

这里有一些关于双重​​检查锁定的代码示例。:

http://javarevisited.blogspot.co.il/2014/05/double-checked-locking-on-singleton-in-java.html

修改

使用double检查的主要好处是你可以使用多个线程运行该函数,而只有在创建新对象的 critical 部分是在锁定下完成的。