常用的设计模式-单例设计模式
Posted 程序员的故事会
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用的设计模式-单例设计模式相关的知识,希望对你有一定的参考价值。
单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。
单例模式有以下特点
1.单例类只能有一个实例
2.单例类必须自己创建自己的唯一实例
3.单例类必须给所有其他对象提供这一实例
基本实现思路
a.构造函数私有化,防止外部调用
b.内部提供一个静态的方法返回该类的引用
下面介绍几种单例模式的写法
饿汉式
public class SingletonUtil {
private static SingletonUtil mInstance = new SingletonUtil();
private SingletonUtil() {}
public static SingletonUtil getInstance() {
return mInstance;
}
}
说明:简单易懂,不存在线程同步问题,随着类的加载,对象也被一并创建。但是若这个类自始至终都没有使用,则会造成内存浪费
懒汉式(一)
public class SingletonUtil1 {
private static SingletonUtil1 mInstance;
private SingletonUtil1() {}
public static SingletonUtil1 getInstance() {
if (mInstance == null) {
mInstance = new SingletonUtil1();
}
return mInstance;
}
}
说明:只有在使用时才创建对象,仅在单线程中使用,多线程中还是会创建多个实例,不能保证只有一个实例
懒汉式(二)
public class SingletonUtil1 {
private static SingletonUtil1 mInstance;
private SingletonUtil1() {}
public static SingletonUtil1 getInstance(){
synchronized(SingletonUtil1.class){
if (mInstance == null) {
mInstance = new SingletonUtil1();
}
}
return mInstance;
}
}
说明:解决了上一个方法中线程不安全的问题,即多线程会创建多个实例,但是效率低下,每次获取的对象时,都需要经过同步锁
懒汉式(三)
public class SingletonUtil1 {
private static volatile SingletonUtil1 mInstance;
private SingletonUtil1() {}
public static SingletonUtil1 getInstance() {
if (mInstance == null) {
synchronized (SingletonUtil1.class) {
if (mInstance == null) {
mInstance = new SingletonUtil1();
}
}
}
return mInstance;
}
}
说明:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。在mInstance上添加了volatile,其目的防止重排序,也保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的
静态内部类
public class SingletonUtil2 {
private SingletonUtil2() {}
public static SingletonUtil2 getInstance() {
return SingletonUtil1Holder.mInstance;
}
public static class SingletonUtil1Holder {
static volatile SingletonUtil2 mInstance = new SingletonUtil2();
}
}
说明:静态内部类不会随着外部类的加载而加载 ,只有静态内部类的静态成员被调用时才会进行加载,所以在你第一次调用getInstance()之前,SingletonUtil1Holder是没有被装载进来的,只有在你第一次调用了getInstance()之后,里面涉及到了return SingletonUtil1Holder.mInstance, 产生了对SingletonUtil1Holder的引用,内部静态类的实例才会真正装载,这里就是懒加载。由于静态内部类的特性,只有在其被第一次引用的时候才会被加载,所以可以保证其线程安全性
容器管理(参考获取系统服务的代码)
public class SingletonUtil3 {
private final static String name = "SingletonUtil3";
private static Map<String, SingletonUtil3> mSingletonMap = new HashMap<>();
static {
mSingletonMap.put("", new SingletonUtil3());
}
private SingletonUtil3() {}
public static SingletonUtil3 getInstance() {
return mSingletonMap.get(name);
}
}
说明:用SingletonUtil3 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度
结束语
文中介绍了几种单例的写法,具体可结合自身项目去考虑使用那种方式去实现。也还有其他的方式来实现,比如枚举等,都是其实现的思路是一样的,保证构造私有,提供一个公有的方法获取类的引用。
以上是关于常用的设计模式-单例设计模式的主要内容,如果未能解决你的问题,请参考以下文章