解释
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
- 单例类只能有一个实例。
-
单例类必须自己创建自己的唯一实例。
-
单例类必须给所有其他对象提供这一实例。
优点:
-
在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
-
避免对资源的多重占用(比如写文件操作)。
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
实现:
UML图:
SingleObject:
Test:
常见5种实现方式
常见的单例模式实现方式有五种:饿汉式
、懒汉式
、双重检测锁式
、静态内部类式
和枚举单例
。而在这五种方式中饿汉式
和懒汉式
又最为常见。下面将一一列举这五种方式的实现方法:
1.饿汉式:
线程安全,调用效率高。但是不能延时加载。
由于该模式在加载类的时候对象就已经创建了,所以加载类的速度比较慢,但是获取对象的速度比较快,且是线程安全的
2.懒汉式:
线程不安全的
这种写法起到了Lazy Loading的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了if (instance \=\= null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。
懒汉式的扩展:
线程安全,调用效率不高,但是能延时加载
在getInstance方法中添加了
synchronized
保证线程安全,缺点:效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。
3.双重同步锁:
线程安全;延迟加载;效率较高。
如代码中所示,我们进行了两次if (instance \=\= null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (instance \=\= null),直接return实例化对象。
4.静态内部类:
静态内部类这种方式和饿汉式机制其实差不多,虽然两者都是采用了类装载的机制来保证初始化实例时只有一个线程,但同的地方在饿汉式方式是类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成实例化。
5.枚举类
线程安全,调用效率高,不能延时加载
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化