私有构造函数

回设计模式

Twitter Facebook

Singleton 模式

Singleton 的英文意义是独身,也就是只有一个人,应用在对象导向语言上,通常翻译作单例:单一个实例(Instance)。 Singleton 模式可以保证一个类别只有一个实例,并提供一个访问(visit)这个实例的方法。
一个Singleton实现即为Java中的java.lang.Runtime类别,每个Java程序运行时都有一个唯一的Runtime对象,可以透 过它提供的静态方法getRuntime()方法来获取这个对象,
例如:
Runtime runtime = Runtime.getRuntime();

获取Runtime对象之后,您可以通过它进行一些外部命令的执行、进行垃圾处理等等指令,您可以开启Runtime.java类别,开头的几行是这样写 的:
public class Runtime {
private static Runtime currentRuntime = new Runtime();

public static Runtime getRuntime() {
return currentRuntime;

}
/** Don’t let anyone else instantiate this class */ private Runtime() {} // 以下略

}

上面结构即采用Singleton模式设计,其结构使用 UML 来表即如下所示:

Singleton

如上所示的,Java使用静态工厂来取得Runtime对象,其中Runtime的建构式被宣告为private,这样可以阻止其他人使用建构方法来建立实例;使用更一般化的表示单例的UML

结构,如下图所示: 有几个实作上面结构的方法,可以在第一次需要实例时再建立对象,也就是采用所谓的Lazy Initialization:
Singleton

public class Singleton {
private static Singleton instance = null;

private Singleton() {
// …
}

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}

return instance;
} // … 其它实作

}

上面的实作适用于单线程的程序,在多线程的程序下,以上的写法在多个执行绪的竞争资源下,将仍有可能产生两个以上的实例,例如下面的情况:
Thread1: if(instance == null) // true
Thread2: if(instance == null) // true

Thread1: instance = new Singleton(); 产生一个实例
Thread2: instance = new Singleton(); 又产生一个实例

Thread1: return instance; 回传一个实例
Thread2: return instance; 又返回一个实例

在多线程的环境下,为了避免资源同时竞争而导致如上产生多个实例的情况,加上同步(synchronized)机制:

不过这种简单的写法不适合用于像服务器这种服务很多执行绪的程序上,同步机制会造成相当的性能 低落,为了顾及Singleton、Lazy Initialization与效能问题,因而有了Double-check Locking的模式:

也就是只有在第一次建立实例时才会进入同步区,之后由于实例已建立,也就不用进入同步区进行锁定。 Java中Runtime类别的作法简单的多,它舍弃了 Lazy Initialization,如果您要取得单例的机会不是很多,可以用这种方式:
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
synchronized static public Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if (instance == null){
synchronized(Singleton.class){
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

public class Singleton {
private static Singleton instance = new Singleton();

private Singleton() {
// …
}

public static Singleton getInstance() {
return instance;
} // 其它实作

}

Singleton本身的观念简单但应用很广,因而很多时候必须对实际环境作一些考量与调整,建议您也看看有关于Singleton的这篇讨论。 如果是Python的话,由于Python是个直译式语言,也没有private修饰,所以没有编译时期检查,实作Singleton的方式之一,就是想 办法于执行时期阻止单一类别实例化两次,一个例子可能像是

: 如果Singleton.__single已经存在,再次实例化并执行__init__初始函式时,将会导致直译失败(您也许想更正式地继承 BaseException来引发一个真正的例外)。

不过,这个程序基本上还是可以有这样的实例方式:
class Singleton:
__single = None
def init(self):
if Singleton.__single:
raise Singleton.__single
Singleton.__single = self
def getSingleton():
if not Singleton.__single:
Singleton.__single = Singleton()
return Singleton.__single
def doSomething(self):
print(“do something…XD”)

singleton = Singleton.getSingleton()
singleton.doSomething()

x = Singleton() # 虽然只能作一次

如果您真的在乎这个不一致性,可以思考一下,其实类别名称只是个名称空间,由于Python是动态语言,真正的型态信息是在对象上,基本上您回的对象只要 有符合的公开定义即可,所以您可以稍微修改一下

: 这么一来,若试图实例化Singleton,就一定会直译失败,您也可以进一步利用Python的特性,定义__new__()方法来达到

需求: 在上例中,一旦已建立了实例,则之后__new__()传回的都是同一个实例。
class Singleton:
__single = None
class __OnlyOne:
def doSomething(self):
print(“do something…XD”)

def __init__(self):
    raise Singleton.__single
    
def getSingleton():
    if not Singleton.__single:
        Singleton.__single = Singleton.__OnlyOne()
    return Singleton.__single

singleton = Singleton.getSingleton()
singleton.doSomething()
class Singleton:
__single = None
def new(clz):
if not Singleton.__single:
Singleton.__single = object.new(clz)
return Singleton.__single

def doSomething(self):
    print("do something...XD")

singleton = Singleton()
singleton.doSomething()

猜你喜欢

转载自blog.csdn.net/weixin_56674140/article/details/115469282