单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
优点
一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
使用场景:
1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
实现方式:
//双重检查加锁
//这种实现方式既可以实现线程安全地创建实例,而又不会对性能造成太大的影响。
//它只是第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。
public class Singleton_1 {
private static volatile Singleton_1 singleton;
private Singleton_1() {
}
public static Singleton_1 getInstance() {
if (singleton == null) {
synchronized (Singleton_1.class) {
if (singleton == null)
singleton = new Singleton_1();
}
}
return singleton;
}
}
//饿汉式
//饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,
//先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。
public class Singleton_2 {
private static Singleton_2 singleton = new Singleton_2();
private Singleton_2() {
}
public static Singleton_2 getInstance() {
return singleton;
}
}
//懒汉式
//线程安全
//懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,
//浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间
public class Singleton_3 {
private static Singleton_3 singleton;
private Singleton_3() {
}
public static synchronized Singleton_3 getInstance() {
if (singleton == null)
singleton = new Singleton_3();
return singleton;
}
}
//登记式/静态内部类
//避免了线程不安全,延迟加载,效率高
public class Singleton_4 {
private static class Singleton_In {
private static final Singleton_4 INSTANCE = new Singleton_4();
}
private Singleton_4() {
}
public static final Singleton_4 getInstance() {
return Singleton_In.INSTANCE;
}
}
//枚举
//不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
public enum Singleton_5 {
INSTANCE;
public void whateverMethod() {
}
}