【一分钟入门设计模式】单例模式
设计模式-分类
设计模式理论上有:3类23种
单例模式-简介
【定义】单例模式是一种对象创建模式,用于生产一个对象的实例,它可以确保系统中一个类只产生一个实例。
【单例的好处】
-
对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销。
-
由于new操作的次数减少,所以系统内存的使用评率也会降低,这将减少GC压力,缩短GC停顿时间。
-
单例模式的使用对于系统的关键组件和频繁使用的对象来说是可以有效的改善系统的性能的。
单例模式-分类
单例模式理论上有:5类8种
单例模式-详解
饿汉模式
饿汉模式——静态常量
【优点】写法简单,类加载时已经完成了实例化,避免了线程同步问题
【缺点】会造成内存浪费
【创建步骤】
- 私有化构造器
- 本类内部创建静态对象实例
- 提供获取静态实例的方法
class HungryMan {
//1. 私有化构造器
private HungryMan() {}
//2.本类内部创建静态对象实例
private static HungryMan instance = new HungryMan();
//3.提供获取静态实例的方法
public static HungryMan getInstance() {return instance;}
}
饿汉模式——静态代码块
【优点】写法简单,类加载时已经完成了实例化,避免了线程同步问题
【缺点】会造成内存浪费
【PS】与饿汉模式——静态常量相比有点脱裤子放屁的感觉,水平有限暂时看不出与前者相比有何优势,但代码倒是多写了几行
【创建步骤】
- 私有化构造器
- 声明静态变量
- 在静态代码块里面实现实例化对象
- 提供获取静态实例的方法
class HungryMan {
//1.私有化构造器
private HungryMan() {}
//2.声明静态变量
private static HungryMan instance;
//3.在静态代码块里面实现实例化对象
static {instance =new HungryMan();}
//4.提供获取静态实例的方法
public static HungryMan getInstance() {return instance;}
}
懒汉模式
懒汉模式——常规懒加载
【优点】的确时起到了懒加载的效果,没有浪费内存
【缺点】只适用于单线程,理论上存在,实际开发也不会用到
【创建步骤】
- 私有化构造器
- 声明静态变量
- 提供一个静态的公有方法,当使用到该方法时才会取创建实例
class LazyMan {
//1.私有化构造器
private LazyMan() {}
//2.声明静态变量
private static LazyMan instance;
//3.提供一个静态的公有方法,当使用到该方法时,会判断实例是否为空,然后再去创建实例
private static LazyMan getInstance() {
if (instance == null) {instance = new LazyMan();}
return instance;
}
}
懒汉模式——同步方法
【优点】的确时起到了懒加载的效果,没有浪费内存,也解决了线程安全问题
【缺点】使用到了同步方法,效率太低,理论上存在,实际开发也不会用到
【创建步骤】
- 私有化构造器
- 声明静态变量
- 提供一个静态的公有方法,当使用到该方法时才会取创建实例,该方法加上synchronized关键字
class LazyMan {
//1.私有化构造器
private LazyMan() {}
//2.声明静态变量
private static LazyMan instance;
//3.提供一个静态的公有方法,当使用到该方法时,会判断实例是否为空,然后再去创建实例
private static synchronized LazyMan getInstance() {
if (instance == null) {instance = new LazyMan();}
return instance;
}
}
懒汉模式——同步代码块
【优点】的确时起到了懒加载的效果,没有浪费内存
【缺点】实际上并没解决线程安全问题,理论上存在,实际开发也不会用到
【创建步骤】
- 私有化构造器
- 声明静态变量
- 提供一个静态的公有方法,当使用到该方法时才会取创建实例,创建实例时使用同步代码块
class LazyMan {
//1.私有化构造器
private LazyMan() {}
//2.声明静态变量
private static LazyMan instance;
//3.提供一个静态的公有方法,当使用到该方法时才会取创建实例,创建实例时使用同步代码块
private static LazyMan getInstance() {
if (instance == null) {
synchronized ("") {instance = new LazyMan();}
}
return instance;
}
}
双重检查
【优点】多线程可用,实现延迟加载,效率高
【缺点】暂无发现
【创建步骤】
- 私有化构造器
- 声明静态变量
- 提供一个静态的公有方法,当使用到该方法时才会取创建实例,过程进行双重检查
class DoubleCheck {
//1.私有化构造器
private DoubleCheck() {
}
//2.声明静态变量
private static DoubleCheck instance;
//3.提供一个静态的公有方法,当使用到该方法时才会取创建实例,过程检查两次
private static synchronized DoubleCheck getInstance() {
if (instance == null) {
synchronized ("") {
if (instance == null) {
instance = new DoubleCheck();
}
}
}
return instance;
}
}
静态内部类
【优点】用类加载机制保证初始化时线程安全;保证懒加载(静态内部类只有调用getInstance方法的时候才会加载,在SingleTon实例化的时候不会加载),且效率高
【缺点】暂无发现
【PS】
- 静态内部类和非静态内部类一样,都不会因为外部类的加载而加载
- 同时静态内部类的加载不需要依附外部类,只会在使用时才加载
- 不过在加载静态内部类的过程中也会加载外部类
【创建步骤】
- 私有化构造器
- 创建静态内部类,该类中有一个SingleTon的静态变量instance
- 提供一个静态的公有方法,获取上一步的instance
class SingleTon {
//1.私有化构造器
private SingleTon() { }
//2.创建静态内部类,该类中有一个SingleTon的静态变量instance
private static class StaticInnerClass {
private static final SingleTon Instance = new SingleTon();
}
//3.提供一个静态的公有方法,获取上一步的instance
public static synchronized SingleTon getInstance() {
return StaticInnerClass.Instance;
}
}
枚举
【优点】没缺点就是它最大的优点
【缺点】暂无
【创建步骤】太简单了直接看代码吧
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
总结
如果你觉得本文在某个时刻带给了你一些新的体会,
我将不胜荣幸,无以所求,只求赞求评论求交流