您现在的位置是:首页 >技术交流 >【设计模式】| 修炼内功 | 23种设计模式——单例模式网站首页技术交流
【设计模式】| 修炼内功 | 23种设计模式——单例模式
设计模式如同织锦之艺术,精心构筑,展示优美。
学习设计模式,犹如追逐清晨的曙光,扉页掀开了人生的新篇章。当你学会设计模式的奥秘,就如同走进了灯火通明的城市,丰富多彩的建筑,让你大开眼界,拥有了整个世界般的视野。
设计模式如同一面明镜,让人自省和反思,看清自己的不足;同时也是一盏明灯,照亮你前行的道路。
它像是一座桥,将你从学生的世界带入到职业的殿堂,让你稳步前行。
学习设计模式,让你的代码更有灵魂,更有温度,更有品味。
它是一种成长,是一种提升,更是一种追求卓越的态度。
让我们一起学习设计模式,饱览编程之美!
快来和?一起学习设计模式叭,修炼内功无上心法!!!
设计模式目录
一. ? 设计模式?知道
23种设计模式可以按照其功能划分为三类,分别是创建型模式、结构型模式和行为型模式,具体如下:
1. 创建型模式:
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
- 单例模式(Singleton)
- 建造者模式(Builder)
- 原型模式(Prototype)
2. 结构型模式:
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰器模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
- 代理模式(Proxy)
3. 行为型模式:
- 职责链模式(Chain of Responsibility)
- 命令模式(Command)
- 解释器模式(Interpreter)
- 迭代器模式(Iterator)
- 中介者模式(Mediator)
- 备忘录模式(Memento)
- 观察者模式(Observer)
- 状态模式(State)
- 策略模式(Strategy)
- 模板方法模式(Template Method)
- 访问者模式(Visitor)
以上23种设计模式都是经典的设计模式,它们被广泛应用于软件开发中,以提高代码的可复用性、扩展性、灵活性和可维护性。
今天我们先来研究一下单例模式
二. ? 目标掌握?单例模式
Ⅰ. 懒汉模式
延迟加载,只有在真正使用的时候,才开始实例化
-
线程安全问题
-
double check 加锁优化
-
编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化的实例,可以通过添加volatile 关键字进行修饰对于volatile 修饰的字段,可以防止指令重排。
class LazySingleton{
// 加volatile 防止多线程情况下,CPU 有可能对指令进行重排序
private volatile static LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance(){
if (instance == null){
synchronized (LazySingleton.class){
if (instance == null){
instance = new LazySingleton();
}
}
}
return instance;
}
}
这样输出的实例都会是同一个,如图:
Ⅱ. 饿汉模式
类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于JVM类加载机制,保证实例的唯一性。
类加载过程:
-
加载二进制数据到内存中,生成对应的Class数据结构
-
连接: a.验证,b.准备 (给类的静态成员变量赋默认值),c.解析
-
初始化: 给类的静态变量赋初值
class HungarySingleton{
private static HungarySingleton instance = new HungarySingleton();
// 使用私有构造函数,防止从外部实例化实例。
private HungarySingleton (){};
public static HungarySingleton getInstance(){
return instance;
}
}
只有在真正使用对应的类时,才会触发初始化 如(当前类是启动类即main函数所在类,直接进行new 操作,访问静态属性、访问静态方 法,用反射访问类,初始化一个类的子类等.)
Ⅲ. 静态内部类
静态内部类模式将单例对象的创建和getInstance()方法的调用分开,只有在第一次调用getInstance()方法时,才会触发静态内部类的加载,进而创建单例对象。由于一个类的静态内部类只会被加载一次,因此静态内部类模式也是线程安全的。
- 本质上是利用类的加载机制来保证线程安全
- 只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一种形式。
public class InnerClassSingletonTest {
public static void main(String[] args) {
new Thread(()->{
InnerClassSingleton instance = InnerClassSingleton.getInstance();
System.out.println(instance);
}
).start();
new Thread(()->{
InnerClassSingleton instance = InnerClassSingleton.getInstance();
System.out.println(instance);
}
).start();
}
}
// 静态内部类模式
class InnerClassSingleton{
private static class InnerClassSingleHolder{
private static InnerClassSingleton instance = new InnerClassSingleton();
}
private InnerClassSingleton(){}
public static InnerClassSingleton getInstance(){
return InnerClassSingleHolder.instance;
}
}
即使是在多线程模式下,获取的也是同一个实例,运行结果如下:
Ⅳ. 枚举类型
是一种利用枚举类型实现的单例模式,它可以保证在任何情况下都只有一个实例对象存在
。枚举类型在Java中天生是单例的,所以枚举实现的单例模式非常简单,同时也具有线程安全、防止反射和序列化攻击的特点。但是,它不太灵活,不能继承其他类或者实现接口。
public enum EnumSingleton {
INSTANCE;
public static EnumSingleton getInstance() {
return INSTANCE;
}
}
Ⅴ. 使用场景
要求生成唯一序列号的环境;
在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;
需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)。
三. ? 学习总结?
本文分享了23种设计模式之一的单例模式,小伙伴们一起干起来叭!!!