这种设计模式是保证类只有一个类Class只有一个实例存在,如果再次新建这个类,之前的类会立即被摧毁。多用于线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序,数据库的连接类等,相当于线程进程中的缓冲区的大小为1,仅允许一个线程进入。
单例模式实现主要是有一下技巧:
1、构造函数私有,如果有克隆函数的话,克隆函数也私用,保证不能再多。
2、在自己内部定义自己的一个实例,只供内部调用。
3、提供了一个供外部访问本class的静态方法,可以直接访问。
可以归纳为如下的Java代码,当然只要你明白以上的思想,在任何一门有类概念的编程语言,都能这样玩。
public class Singleton {
private static Singleton uniqueInstance = null;
private Singleton() {
// Exists only to defeat instantiation.
}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// Other methods...
}
下面以Java为例,说明以上代码,请看如下完整代码,一个作为对照的普通类NormalClass,实在是没有任何特别了,另一个是被单例的类Singleton。在主函数中,分别为这两个类创造2个实例,分别设置其中的Name。
class NormalClass{
// name及其getter与setter
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Singleton {
// name及其getter与setter
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 以下代码,该类只能有一个实例
private Singleton() {
} // 私有无参构造方法
// 在自己内部定义自己的一个实例,只供内部调用
private static Singleton Singleton = null;
// 这个类必须自动向整个系统提供这个实例对象
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
if (Singleton == null) {
Singleton = new Singleton();
}
return Singleton;
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton1=Singleton.getInstance();
Singleton singleton2=Singleton.getInstance();
singleton1.setName("aaa");
singleton2.setName("bbb");
System.out.println("singleton1:"+singleton1.getName()+","+"singleton2:"+singleton2.getName());
System.out.println(singleton1==singleton2);
NormalClass normalclass1=new NormalClass();
NormalClass normalclass2=new NormalClass();
normalclass1.setName("aaa");
normalclass2.setName("bbb");
System.out.println("normalclass1:"+normalclass1.getName()+","+"normalclass2:"+normalclass2.getName());
System.out.println(normalclass1==normalclass2);
}
}
运行效果如下图所示:
如果这个类没有被单例,很明显,应该如下所示,不同实例的类成员是分别独立的。你可以为其设置不同的值是相互不影响的。
但被单例的singleton,无论你为其设置多少个实例,其仅保留最后一个实例,之前的实例全部被最后一个实例替代,操作任一一个实例,实际就是在操作一个实例。
因此,singleton1与singleton2实际是完全相同的,都是同一个东西,因此里面的name,先被设置aaa之后,又被设置为bbb。
Singleton无法通过new关键字创建,因为其构造函数被私有了,仅能通过在其内部对外提供的getInstance来新建,getInstance方法写得非常明显,如果没有Singleton就给你创建一个,如果有,就返回自己给你,从而达到单例的效果。