设计模式-单例模式(Singleton Pattern)
单例模式通俗的解释就是一个类只有唯一的对象实例 ,那要怎么才能实现这一点呢?首先要知道所以的单例模式都是用静态方式实现的,单例对象实例都是存储在静态共享区。好了,知道了这些,下面就介绍具体是怎么实现的。
实现方法 一般要做这三件事! 1、构造函数私有化(防止使用 new() 方法创建出多个对象实例) 2、进行初始化生成一个静态的对象实例(在不同时间生成,就产生了不同的写法) 3、提供 getInstance() 方法,返回一个生成的那个对象实例(方法名可以自己定义,只是习惯写成 getInstance)
常见类型 第一种:饿汉式(在类加载时就完成了初始化) 第二种:懒汉式(在类加载时不初始化而是在 getInstance() 方法中判断对象是否为 null,为空才初始化) 第三种:静态内部类(在静态内部类中,初始化对象实例)
代码实现 1、饿汉式(推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package test; /** * 饿汉式 * 线程是安全的 */ public class SingleInstance { //在类加载时就完成了初始化,final使对象实例不能改变(可写可不写,推荐写,javaApi里的单例也用了这个关键字) //final(保证对象的安全发布,防止对象引用被其他线程在对象被完全构造完成前拿到并使用) private static final SingleInstance INSTANCE = new SingleInstance(); private SingleInstance() {} //构造函数私有化 private static SingleInstance getInstance() { //获取对象的方法 return INSTANCE; } public static void main(String[] args) { SingleInstance test1 = SingleInstance.getInstance(); SingleInstance test2 = SingleInstance.getInstance(); System.out.println(test1 == test2); } }
2、懒汉式(不推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package test; /** * 懒汉式 * 线程不安全型 */ public class SingleInstance { //在类加载时,只进行声明,不进行初始化,不能写final,因为后面要赋值修改 private static SingleInstance INSTANCE; private SingleInstance() {} //构造函数私有化 private static SingleInstance getInstance() { //获取对象的方法 if(INSTANCE == null) { INSTANCE = new SingleInstance(); } return INSTANCE; } public static void main(String[] args) { SingleInstance test1 = SingleInstance.getInstance(); SingleInstance test2 = SingleInstance.getInstance(); System.out.println(test1 == test2); } }
上面写法在多线程需要同步的环境下不能正常工作,那把它改为线程安全型的。 改为线程安全型的懒汉式,只需要在 getInstance() 方法前加上同步锁关键字 synchronized 即可,但加了同步锁之后,效率会变得很低,毕竟大多数情况下不需要同步的。所以推荐大家使用第一种方式。
3、静态内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package test; /** * 静态内部类 * 资源利用率高 */ public class SingleInstance { //在静态内部类中,初始化对象实例,相比饿汉式,不执行getInstance()就不会被实例,节省资源 private static class SingletonHelp{ static final SingleInstance instance = new SingleInstance(); } private SingleInstance() {} //构造函数私有化 private static SingleInstance getInstance() { //获取对象的方法 return SingletonHelp.instance; } public static void main(String[] args) { SingleInstance test1 = SingleInstance.getInstance(); SingleInstance test2 = SingleInstance.getInstance(); System.out.println(test1 == test2); } }
总结 对象的创建比较消耗资源,只需要一个时,比如资源共享的情况下,就可以使用单例模式,这样可以避免由于资源操作时导致的性能或损耗等。 再次说明,一般采用饿汉式,如果对资源要求利用率高,可以采用静态内部类,不建议采用懒汉式。