设计模式原理

本文详细探讨了抽象工厂模式,包括其定义、类图、优点(如单一职责和开闭原则)以及应用实例。同时,深入剖析了单例模式(懒汉、恶汉、静态内部类实现)及其优缺点,特别关注线程安全和反射对单例模式的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

设计模式原则

 一、抽象工厂模式

1.1 定义

1.2 类图

1.3 优点

1.4 例子

二、单例模式

2.1 定义

2.2 优缺点

2.3 应用场景

Runtime.java

DefaultSingletonBeanRegistry.java

ReactiveAdapterRegistry.java

Currency.java

2.4 实现方式

1、懒汉模式

2、恶汉模式

3、静态内部类

反射打破单例模式情况


设计模式原则

开闭原则 对扩展开放,对修改关闭

单⼀职责原则 ⼀个类只负责⼀个功能领域中的相应职责

⾥⽒替换原则 所有引⽤基类的地⽅必须能透明地使⽤其⼦类的对象

依赖倒置原则 依赖于抽象,不能依赖于具体实现

接⼝隔离原则 类之间的依赖关系应该建⽴在最⼩的接⼝上

合成/聚合复⽤原则 尽量使⽤合成/聚合,⽽不是通过继承达到复⽤的⽬的

迪⽶特法则 ⼀个软件实体应当尽可能少的与其他实体发⽣相互作⽤

 一、抽象工厂模式

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类加载机制,保证实例唯一性。

类加载是就创建对象、比较常用,但是容易浪费空间。

优点:线程安全、没有加锁,执行效率快

缺点:浪费空间

类加载过程:

  1. 加载二进制字节码数据到内存中,生成对应class数据结构
  2. 连接:a:验证、b:准备(给类的静态成员变量赋默认值),c:解析
  3. 初始化:给类静态变量赋初值
  4. 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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值