概述
设计模式之创建型模式:单例模式
- 一、设计模式概述
- 二、单例模式概述
- 三、单例模式实现
- 1. 饿汉式实现
- 2. 懒汉式实现
- 2.1 多线程不安全的实现
- 2.2 多线程安全的实现
- 2.2.1 synchronized实现
- 2.2.2 双重检查实现
- 2.2.3 静态内部类实现
- 3. 枚举实现
- 四、单例模式在JDK源码中的应用示例
一、设计模式概述
设计模式是基于设计模式原则的基础上,由众多软件开发人员对所遇到的软件工程设计问题所总结的经验,它是某类问题的解决方案,代表了某类问题的最佳实践,它的最终目的是为了提高软件的可维护性,可读性,通用性,可扩展性等。
设计模式最经典的书籍就是由“四人组GOF”所编写的【设计模式】,该书将设计模式总结为三种类型,共23种,我后续的设计模式就按照这23种设计模式逐一讲解。
23种设计模式分别如下:
- 创建型模式(5种):单例模式,抽象工厂模式,原型模式,建造者模式,工厂模式。
- 结构型模式(7种):适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式。
- 行为型模式(11种):模板方法模式,命令模式,访问者模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式。
本文讲解创建型模式中的单例模式。
二、单例模式概述
单例设计模式就是保证在整个软件系统中,对某个类只能存在一个对象实例,该对象实例由类提供一个静态方法获取。
单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
基于单例模式的特点,其应用场景如下:
- 对于一些重量级的对象(创建时耗时或者耗费资源过多)
- 需要频繁进行创建和销毁的对象
- 经常用到的工具类对象
- 频繁访问数据库或文件的对象
- …
三、单例模式实现
1. 饿汉式实现
所谓饿汉式实现就是指,不论这个类对象是否会用到,在类加载的时候就进行实例化。
饿汉式单例模式,直接对静态变量进行实例化,代码实现如下:
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部直接创建对象实例
private final static Singleton instance = new Singleton();
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
饿汉式单例模式,将静态变量在静态代码块中进行实例化,代码实现如下:
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部创建对象实例
private static Singleton instance;
static { // 在静态代码块中,创建单例对象
instance = new Singleton();
}
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
2. 懒汉式实现
所谓懒汉式实现是指只有用到某个类对象时才会创建,用不到就不会创建,可以减少系统资源浪费。具体实现方法包括多线性不安全和多线程安全两种类型,对应线程不安全的实现只适用于单线程使用。
2.1 多线程不安全的实现
- 代码实现:
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,当使用到该方法时,才去创建 instance
//即懒汉式
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 为什么多线程不安全?
因为在多线性环境下,有可能多个线程同时进入if代码块,这样就会导致多个线程都进行实例化操作,产生不一样的对象。
2.2 多线程安全的实现
2.2.1 synchronized实现
代码实现:
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 分析
因为在获取实例化对象的方法上添加了同步关键字,就可以保证每次只有一个线程进入该方法,保证了多线程必然得到的是同一个实例化对象。但是这种实现方法的缺点是造成效率降低,因为每一个线程访问都要进行同步,但理论上只要一个线程完成实例化后,其它线程就不会再存在得到不同对象的问题了,因此可以不需要同步操作了。
为了解决该实现方法造成的效率低的问题,提出双重检查实现方法,该方法既可以保证线程安全,又可以尽可能的少的使用同步代码块。
2.2.2 双重检查实现
- 代码实现
class Singleton {
private static volatile Singleton instance;//必须使用volatile关键字,防止指令重排
private Singleton() {}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
//同时保证了效率, 推荐使用
public static Singleton getInstance() {
if(instance == null) {//如果尚未创建对象,可能多个线程进入下面的代码块
synchronized (Singleton.class) {//保证一次只能有一个线程进入其代码块
if(instance == null) {//假设一个线程已经实例化了对象,如果再有线程进来,就会发现instance不为null,就不会再实例化对象
instance = new Singleton();
}
}
}
return instance;
}
}
2.2.3 静态内部类实现
- 代码实现
class Singleton {
//构造器私有化
private Singleton() {}
//写一个静态内部类,该类中有一个静态属性 Singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
- 分析
静态内部类在外面的类加载的时候不会初始化,只有使用到内部类时才会由jvm类加载器加载,而JVM可以保证线程的安全性,因此实现了线程安全,并且很明显实现了懒加载。
3. 枚举实现
- 代码实现
enum Singleton {
INSTANCE; //属性
}
- 分析
枚举实现单例模式是官方推荐的一种方法,枚举实现非常简单,并且基于JVM保证了线程安全。
四、单例模式在JDK源码中的应用示例
JDK中Runtime类就是实现了饿汉式单例模式,部分源码如下:
最后
以上就是欢呼鞋子为你收集整理的设计模式之创建型模式:单例模式一、设计模式概述二、单例模式概述三、单例模式实现四、单例模式在JDK源码中的应用示例的全部内容,希望文章能够帮你解决设计模式之创建型模式:单例模式一、设计模式概述二、单例模式概述三、单例模式实现四、单例模式在JDK源码中的应用示例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复