Re:设计单例singleton
一,什么是单例模式
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
二,单例模式有什么用
- 1、要求生产唯一序列号。
- 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
三,如何设计单例模式
分析:
1,某个类只能有一个实例——构造器私有化
2,它必须自行创建这个类——含有一个该类的静态变量来保存这个唯一的实例
3,它必须自行向整个系统提供这个类——(1)直接暴露,(2)用静态的get方法获取
创建:
饿汉式:直接创建对象,不存在线程安全问题
1,直接实例化(简洁直观)
/** * 在类初始化时直接创建实例对象,不管是否需要这个对象都会创建 * * (1)构造函数私有化 * (2)自行创建并用静态变量保存 * (3)向外提供这个实例 * (4)强调这是一个实例,用final修饰 */ public class Singleton1 { private final static Singleton1 INSTANCE = new Singleton1(); private Singleton1(){ } }
2,枚举式(最简洁)
/** * 枚举类型表示该类型的对象是有限的几个 * 限定为一个,就成了单例 */ public enum Singleton2 { INSTANCE }
3,静态代码块(适合复杂实例化)
public class Singleton3 { private final static Singleton3 INSTANCE ; static { INSTANCE = new Singleton3(); //再此可以读取一些初始化数据,外部文件,配置文件等 //Properties property = new Properties(); } private Singleton3(){ } }
懒汉式:延迟创建对象
1,线程不安全(适用于单线程)
** * 延迟创建实例对象 * (1)构造函数私有化 * (2)用一个静态变量保存这个唯一的实例 * (3)提供一个静态方法,获取这个实例对象 */ public class Singleton4 { private static Singleton4 INSTANCE ; private Singleton4(){ } public static Singleton4 getInstance() throws InterruptedException { //如果实例变量为空,就创建一个实例,否则直接返回这个实例 if (INSTANCE == null){ Thread.sleep(2000); INSTANCE = new Singleton4(); } return INSTANCE; } }
2,线程安全(适用于多线程)
/** * 延迟创建实例对象 * (1)构造函数私有化 * (2)用一个静态变量保存这个唯一的实例 * (3)提供一个静态方法,获取这个实例对象 */ public class Singleton5 { private static Singleton5 INSTANCE ; private Singleton5(){ } public static Singleton5 getInstance() throws InterruptedException { if (INSTANCE == null) { synchronized (Singleton5.class) { //如果实例变量为空,就创建一个实例,否则直接返回这个实例 if (INSTANCE == null) { Thread.sleep(2000); INSTANCE = new Singleton5(); } } } return INSTANCE; } }
3,静态内部类(适用于多线程)
/** * 在内部类被加载和初始化时,才创建INSTANCE实例对象 * 静态内部类不会自随着外部类的加载和初始化而初始化,它是要单独加载和初始化的,是线程安全的 */ public class Singleton6 { private Singleton6(){ } private static class Inner { private final static Singleton6 INSTANCE = new Singleton6() ; } public static Singleton6 getInstance(){ return Inner.INSTANCE; } }