目录
DefaultSingletonBeanRegistry.java
设计模式原则
开闭原则 对扩展开放,对修改关闭
单⼀职责原则 ⼀个类只负责⼀个功能领域中的相应职责
⾥⽒替换原则 所有引⽤基类的地⽅必须能透明地使⽤其⼦类的对象
依赖倒置原则 依赖于抽象,不能依赖于具体实现
接⼝隔离原则 类之间的依赖关系应该建⽴在最⼩的接⼝上
合成/聚合复⽤原则 尽量使⽤合成/聚合,⽽不是通过继承达到复⽤的⽬的
迪⽶特法则 ⼀个软件实体应当尽可能少的与其他实体发⽣相互作⽤
一、抽象工厂模式
1.1 定义
抽象工厂模式(Abstract FactoryPattern)围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂
1.2 类图
1.3 优点
单一职责
开闭原则
1.4 例子
Connection.java
二、单例模式
2.1 定义
保证一个类只有一个实例,并且提供一个全局访问点
2.2 优缺点
优点:一个单例类只存在一个实例,减少开销、避免创建和销毁是对资源的多重占用
确定:没有抽象层、难以扩展、违反设计模式思想的单一职责原则。
2.3 应用场景
线程池、连接池等情况
Runtime.java
标准的恶汉模式
DefaultSingletonBeanRegistry.java
懒汉模式
ReactiveAdapterRegistry.java
volatile的懒汉模式
Currency.java
带序列化和反序列化
2.4 实现方式
1、懒汉模式
需要优化:线程安全、双重校验、防止指令重排 voilatile
为什么要用voilatile?
因为可见性、防止指令重排,new过程不是原子操作。会经历1、开启堆空间 2、构造方法初始化对象 3、引用变量指向堆内存空间
package com.example.demo.designPattern.singleton;
/**
* @author 10450
* @description 懒汉模式
* 并发情况下,有可能
* @date 2022/9/15 13:58
*/
public class LazySingletonTest {
public static void main(String[] args){
new Thread(()->{
LazySingleton intance = LazySingleton.getSingleton();
System.out.println(intance);
}).start();
new Thread(()->{
LazySingleton intance = LazySingleton.getSingleton();
System.out.println(intance);
}).start();
new Thread(()->{
LazySafeSingleton intance = LazySafeSingleton.getSingleton();
System.out.println(intance);
}).start();
new Thread(()->{
LazySafeSingleton intance = LazySafeSingleton.getSingleton();
System.out.println(intance);
}).start();
new Thread(()->{
LazyVolatileSingleton intance = LazyVolatileSingleton.getSingleton();
System.out.println(intance);
}).start();
new Thread(()->{
LazyVolatileSingleton intance = LazyVolatileSingleton.getSingleton();
System.out.println(intance);
}).start();
}
}
/**
* 多线程不安全
*/
class LazySingleton{
private static LazySingleton instance;
private LazySingleton(){
}
public static LazySingleton getSingleton(){
if(instance==null){
try{
Thread.sleep(5000);
instance = new LazySingleton();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
return instance;
}
}
/**
* 多线程安全,但是指令重排有问题
*/
class LazySafeSingleton{
private static LazySafeSingleton instance;
private LazySafeSingleton(){
}
public static LazySafeSingleton getSingleton(){
if(instance==null){
synchronized (LazySafeSingleton.class){
if(instance==null){
try{
Thread.sleep(5000);
instance = new LazySafeSingleton();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
return instance;
}
}
/**
* 防止指令重排
*/
class LazyVolatileSingleton{
private volatile static LazyVolatileSingleton instance;
private LazyVolatileSingleton(){
}
public static LazyVolatileSingleton getSingleton(){
if(instance==null){
synchronized (LazyVolatileSingleton.class){
if(instance==null){
try{
Thread.sleep(5000);
instance = new LazyVolatileSingleton();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
return instance;
}
}
2、恶汉模式
类加载的初始化节点完成实例初始化。本质就是JVM类加载机制,保证实例唯一性。
类加载是就创建对象、比较常用,但是容易浪费空间。
优点:线程安全、没有加锁,执行效率快
缺点:浪费空间
类加载过程:
- 加载二进制字节码数据到内存中,生成对应class数据结构
- 连接:a:验证、b:准备(给类的静态成员变量赋默认值),c:解析
- 初始化:给类静态变量赋初值
-
package com.example.demo.designPattern.singleton; /** * @author 10450 * @description 恶汉模式 * 类加载的时候完成初始化 * @date 2022/9/15 14:23 */ public class HungrySingletonTest { public static void main(String[] args) { System.out.println(HungrySingleton.getInstance()); System.out.println(HungrySingleton.getInstance()); } } class HungrySingleton{ private static HungrySingleton instance = new HungrySingleton(); private HungrySingleton(){ } public static HungrySingleton getInstance(){ return instance; } }
3、静态内部类
优点:懒加载,线程安全,效率较⾼,实现简单
- 本质上利用类的加载机制保证线程安全
- 只要在实际使用的时候才会触发累的初始化,也是懒加载的一种
-
package com.example.demo.designPattern.singleton; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * @author 10450 * @description 静态内部类 * 可以防止通过反射,实现多利 * @date 2022/9/15 14:28 */ public class InnerClassSingletonTest { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { new Thread(()->{ System.out.println(InnerClassSingleton.getInstance()); }).start(); new Thread(()->{ System.out.println(InnerClassSingleton.getInstance()); }).start(); //利用反射方式创建类对象打破单例模式,实现多利 Constructor<InnerClassSingleton> declaredConstructor = InnerClassSingleton.class.getDeclaredConstructor(); declaredConstructor.setAccessible(true); InnerClassSingleton innerClassSingleton = declaredConstructor.newInstance(); InnerClassSingleton instance = InnerClassSingleton.getInstance(); System.out.println(innerClassSingleton); System.out.println(instance); } } class InnerClassSingleton{ private static class InnerClassSingletonHolder{ private static InnerClassSingleton instance = new InnerClassSingleton(); } private InnerClassSingleton(){ } public static InnerClassSingleton getInstance(){ try { System.out.println(1); Thread.sleep(8000); System.out.println(2); } catch (InterruptedException e) { e.printStackTrace(); } return InnerClassSingletonHolder.instance; } }
反射打破单例模式情况
通过反射方式创建类,可以打破单例模式,实现多例效果,
【恶汉模式】、【内部类模式】可以判断防止多例
package com.example.demo.designPattern.singleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author 10450
* @description 反射攻击
* @date 2022/9/15 15:03
*/
public class InnerClassReflexSingletonTest {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//单例保护防止多利情况下:
Constructor<InnerClassProtectSingleton> declaredConstructor = InnerClassProtectSingleton.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
InnerClassProtectSingleton innerClassSingleton = declaredConstructor.newInstance();
InnerClassProtectSingleton instance = InnerClassProtectSingleton.getInstance();
System.out.println(innerClassSingleton);
System.out.println(instance);
}
}
/**
* 防止多例
*/
class InnerClassProtectSingleton {
private static class InnerClassSingletonHolder {
private static InnerClassProtectSingleton instance = new InnerClassProtectSingleton();
}
private InnerClassProtectSingleton() {
//添加校验,抛异常
if (InnerClassSingletonHolder.instance != null) {
throw new RuntimeException("单例模式,不运行重复创建");
}
}
public static InnerClassProtectSingleton getInstance() {
return InnerClassProtectSingleton.InnerClassSingletonHolder.instance;
}
}