一、定义及应用
单例模式,是一种常用的软件设计模式,在使用这个设计模式时,单例对象的类要保证只有一个实例存在。
许多时候整个系统只需要有一个全局对象,这样有利于我们协调整个系统的行为。比如服务器程序中,服务器程序的配置信息存储在一个文件中,使用一个单例对象同意读取,服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了复杂环境下的配置管理。同样,线程池、连接池也是通过单例模式进行管理。
二、实现
1)、两懒汉方式
public class Singleton{//非线程安全 private static Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance==null){ instance=new singleton(); } return instance; } } public class Singleton{//线程安全 private static Singleton instance; private Singleton(){}; public static synchronized Singleton getInstance(){ if(instance==null){ instance=new singleton(); } return instance; } }
2)、饿汉方式
public class Singleton{ private static final Singleton instance=new Singleton(); private Singleton(){}; public static Singleton getInstance(){ return instance; } }
3)、内部类
public class Singleton{//懒加载 线程安全 private static class SingletonHolder{ private static final Singlton instance=new Singleton(); } private Singleton(){}; public static Singleton getInstance(){ return SingletonHolder.instance; } }
4)、枚举
public enum Singleton{ INSTANCE; //....other function }
写枚举单例的方式,它可能包含实例变量和实例方法,但是简单来说我什么都没用,需要注意的是如果你使用实例方法,你就需要确保方法的线程安全性,避免它会影响对象的状态。通常情况下枚举里面创建实例是线程安全的,但是其它的方法就需要编程者自己去考虑了。
5)、双校验
public class Singleton{ private volatile static Singleton instance;//volatile关键字保证当instance变量被初始 private Singleton(){};//化Singleton实例后,多个线程正确的处理instance变量 public static Singleton getInstance(){ if(instance==null){ synchronize(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } }
三、防止破坏单例模式
1、阻止clone()方法创建单例实例的另一个实例
1)override clone()方法
protected Object clone() throws CloneNotSupportedException{ throw new CloneNotSupportedException(); }
2)一个是单例类一定要是final的,这样用户就不能继承它了
如果有其他方法可以交流交流!
2、防止反射破坏
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Singletom { private static final Singletom instance=new Singletom(); private Singletom(){}; public static Singletom getInstance(){ return instance; } public static void main(String [] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{ Class<Singletom> clazz = Singletom.class; Constructor<Singletom> constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); System.out.println(Singletom.instance == constructor.newInstance()); } }