对于系统中的某一些类来说,只有一个实例很重要。例如在一个系统中可以存在多个打印的任务,但是只能有一个正在工作的任务。一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。
单例模式的要点有三个:
- 某一个类只能有一个实例对象
- 它必须自行创建这个实例
- 它必须自行向整个系统提供这个实例
单例模式的目的:保证该类只有一个对象。
- 第一步:将构造方法私有化
- 第二步:创建一个成员变量
- 第三步:通过一个公共的方法提供访问
单例模式的优点:
- 实例控制:单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
- 灵活性:因为类控制了实例化过程,所以类可以灵活更改实例化过程。
Singleton模式主要作用是保证在Java应用程序中,一个类class只有一个实例存在。一般Singleton模式通常有两种形式。
第一种懒汉式:可以理解为它只有在不得不去做某件事情的时候再去做。代码如下:
public class SingletonClass {
//创建私有成员变量
private static SingletonClass mInstance=null;
//构造器私有化
private SingletonClass() {
}
//提供公共的方法来访问
public static synchronized SingletonClass getmInstance(){
if (mInstance==null){
mInstance=new SingletonClass();
}
return mInstance;
}
}
测试:
public class Test{
public static void main(String[] args) {
SingletonClass s1=SingletonClass.getmInstance();
SingletonClass s2=SingletonClass.getmInstance();
System.out.println(s1);
System.out.println(s2);
/*
控制台打印:
com.myblog.controller.SingletonClass@72ea2f77
com.myblog.controller.SingletonClass@72ea2f77
*/
}
}
饿汉式:
public class Singleton {
// 在自己内部定义自己的一个实例,只供内部调用
private static Singleton msingleton=new Singleton();
//构造器私有化
private Singleton() {
}
//提供公共的方法来访问
public static Singleton getInstance(){
return msingleton;
}
}
测试:
public class Test{
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
System.out.println(s1);
System.out.println(s2);
}
}
/*
控制台打印:
com.myblog.controller.Singleton@72ea2f77
com.myblog.controller.Singleton@72ea2f77
*/
懒汉式和饿汉式的区别:
- 饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。
- 从实现方式来讲他们最大的区别就是懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,饿汉式无需关注多线程问题、写法简单明了、能用则用。但是它是加载类时创建实例、所以如果是一个工厂模式、缓存了很多实例、那么就得考虑效率问题,因为这个类一加载则把所有实例不管用不用一块创建。
- 简单来说一个是饿的不行了,上来就吃,撑死也无所谓。一个是我不饿,我都懒的吃。我啥时候饿了啥时候再吃,最后懒的被饿死了。