对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
1.懒汉式
懒汉式和饿汉式的区别在于建立单例对象的时间不同,懒汉式是在你真正需要用到的时候才去创建对象
public class Singleton {
//4.定义一个变量来存储创建好的实例
//5.因为这个变量要在静态方法使用所以要加static
private static Singleton instance = null;
//1.私有化构造方法
private Singleton() {
}
//2.定义一个方法来为客户端提供类实例
//3.这个方法要定义成类方法,即加static
public Singleton GetInstance() {
//6.判断变量是否有值
if(instance==null) {
//如果没有就创建一个
instance=new Singleton();
}
//如果有就直接使用
return instance;
}
}
我们新建一个测试类,输出jvm1和jvm2的地址是一样的,因为是同一个对象
public class SMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton singleton1=Singleton.GetInstance();
Singleton singleton2=Singleton.GetInstance();
System.out.println("输出singleton1:"+singleton1);
System.out.println("输出singleton2:"+singleton2);
}
}
特点:实现了延迟加载,但在多线程情况下可能会出现问题,不能保证线程安全。
public class Singleton
{
private static Singleton singleton;
//定义一个只读静态对象
//且这个对象是在程序运行时创建的
//由于提供给 lock 关键字的参数必须为基于引用类型的对象,这个引用类型的对象不能为 null,singleton一开始为 null ,所以是无法实现加锁的,所以必须要再创建一个对象即 syncObject 来定义加锁的范围。
private static readonly object syncObject = new object();
private Singleton()
{}
public static Singleton GetInstance()
{
//第一重 singleton == null 为了性能
if (singleton == null)
{
lock (syncObject)
{
//第二重 singleton == null
if (singleton == null)
{
singleton = new Singleton();
}
}
}
return singleton;
}
}
2.饿汉式
当整个类被加载的时候,就会自行初始化 singleton 这个静态只读变量。
public class Singleton
{
private static readonly Singleton singleton = new Singleton();
private Singleton()
{
}
public static Singleton GetInstance()
{
return singleton;
}
}