单例模式
设计模式中最简单的一种模式,即保证系统运行是,运行的类只有一个实例对象。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式注意事项:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
优点:
- 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
- 避免对资源的多重占用(比如写文件操作)。
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
代码实例:
public class SingletonObject {
//创建 SingletonObject 的对象
private static SingletonObject instance = new SingletonObject ();
//让构造函数为 private,这样该类就不会被实例化
private SingletonObject (){}
//获取唯一可用的对象
public static SingletonObject getInstance(){
return instance;
}
public void show(){
System.out.println("这是一个单例模式的例子");
}
}
public class SingletonPatternDemo {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingletonObject () 是不可见的
//SingletonObject object = new SingletonObject ();
//获取唯一可用的对象
SingletonObject object = SingletonObject.getInstance();
//调用方法
object.show();
}
}
单例模式的几种实现方式
- 饿汉式
最上面的例子,也是最常用的方式,缺点在于会产生很多垃圾对象,消耗内存。
- 懒汉式 线程不安全
类中定义instance ,但是不实例化,等使用时在实例化,也就是所谓的懒加载。但是这种情况不适用于多线程,多线程的时候这就不是单例了,同时可能出现线程安全问题。
demo:
public class Singleton {
private static Singleton instance; // 先定义出instance,但是不实例化
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // 用到该类的时候才new出对象
}
return instance;
}
}
- 懒汉式 线程安全
和上面的模式相同只是在获取对象的时候用了synchronize关键字,保证线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 双检锁/双重校验锁
在懒汉式线程安全模式下,对事先定义的instance进行可见性操作,即加上volatile 关键字,保证,线程安全也保证对象可见,保证不会出现单例对象多例出现的情况
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 枚举
个人常用的类型,多种筛选类型时使用直观明了