> 文章列表 > 23种设计模式

23种设计模式

23种设计模式

参考链接:

  • 【狂神说Java】通俗易懂的23种设计模式教学(停更)_哔哩哔哩_bilibili

  • 23种设计模式【狂神说】_狂神说设计模式_miss_you1213的博客-CSDN博客

1. 单例模式

参考链接:

  • 【狂神说Java】单例模式-23种设计模式系列_哔哩哔哩_bilibili

  • JAD Java Decompiler Download Mirror

1.1 饿汉式单例

 package com.study.singleton;​/*** @ClassName HungryMan* @Description 饿汉式单例模式【不安全】* @Author Jiangnan Cui* @Date 2023/3/20 22:24* @Version 1.0*/public class HungryMan {/*** 缺点:类加载期间就创建对象,容易造成资源浪费。即:当该类中放置了很多资源时,最开始加载可能会浪费空间,因为加载了也不使用。*/private byte[] data1 = new byte[1024*1204];private byte[] data2 = new byte[1024*1204];private byte[] data3 = new byte[1024*1204];private byte[] data4 = new byte[1024*1204];private byte[] data5 = new byte[1024*1204];​/*** 私有构造方法限制产生多个对象*/private HungryMan() {}​/*** 最开始就创建对象,保证只有一个对象*/private static final HungryMan HUNGRY_MAN = new HungryMan();​/*** 通过该方法获得实例对象* @return*/public static HungryMan getInstance(){return HUNGRY_MAN;}}​

1.2 懒汉式单例

 package com.study.singleton;​/*** @ClassName LazyMan* @Description 懒汉式单例模式:用的时候再创建【不安全】  *              单线程下安全,多线程下存在并发安全问题* @Author Jiangnan Cui* @Date 2023/3/20 22:33* @Version 1.0*/public class LazyMan {/*** 私有构造方法限制产生多个对象*/private LazyMan(){// 此处为了测试多线程并发安全问题System.out.println(Thread.currentThread().getName() + " is ok");}​private static LazyMan lazyMan = null;​/*** 通过该方法获得实例对象* @return*/public static LazyMan getInstance(){if (lazyMan == null) {lazyMan = new LazyMan();}return lazyMan;}​public static void main(String[] args) {// 多线程并发时存在线程安全问题for (int i = 0; i < 10; i++) {new Thread(()->{LazyMan.getInstance();}).start();}/*** 输出的一个结果举例:* Thread-0 is ok* Thread-3 is ok* Thread-2 is ok* Thread-1 is ok*/}}​

1.3 懒汉式单例-DCL

 package com.study.singleton;​import com.sun.org.apache.bcel.internal.generic.I2B;​import java.lang.reflect.Constructor;import java.lang.reflect.Field;​/*** @ClassName LazyMan2* @Description 懒汉式单例模式+双重锁校验优化+防止指令重排:DCL懒汉式【不安全】】*              解决多线程下存在并发安全问题* @Author Jiangnan Cui* @Date 2023/3/20 22:33* @Version 1.0*/public class LazyMan2 {private static boolean secret = false;// 红绿灯​/*** 私有构造方法限制产生多个对象*/private LazyMan2(){// 解决反射破坏单例问题synchronized (LazyMan2.class) {if (secret == false) {secret = true;} else {throw new RuntimeException("不要试图使用反射破坏异常!");}}// 此处为了测试多线程并发安全问题System.out.println(Thread.currentThread().getName() + " is ok");}​/*** 加volatile防止指令重排*/private volatile static LazyMan2 lazyMan2 = null;​/*** 通过该方法获得实例对象* @return*/public static LazyMan2 getInstance(){if (lazyMan2 == null) {synchronized (LazyMan2.class) {if (lazyMan2 == null) {/*** new对象的过程中,不是一个原子性操作* 1.分配内存空间* 2.执行构造方法,初始化对象* 3.把这个对象指向这个空间** CPU指令重排:1、3、2,此时lazyMan2还没有完成构造,需要加volatile保证指令不重排*/lazyMan2 = new LazyMan2();}}}return lazyMan2;}​public static void main(String[] args) throws Exception {/*** 反射可以破坏单例*///        LazyMan2 instance1 = LazyMan2.getInstance();​// 2.再次调用反射:获取字段,无视私有Field secret = LazyMan2.class.getDeclaredField("secret");secret.setAccessible(true);//无视私有构造器​// 1.利用反射Constructor<LazyMan2> declaredConstructor = LazyMan2.class.getDeclaredConstructor(null);// 无视私有构造器declaredConstructor.setAccessible(true);// 创建新对象LazyMan2 instance1 = declaredConstructor.newInstance();​// 3.重新设置secret.set(instance1, false);​        // 再次利用反射创建对象LazyMan2 instance2 = declaredConstructor.newInstance();​System.out.println("instance1 = " + instance1);System.out.println("instance2 = " + instance2);}}​

1.4 静态内部类

 package com.study.singleton;​/*** @ClassName StaticInnerClass* @Description 静态内部类单例模式【不安全】* @Author Jiangnan Cui* @Date 2023/3/20 23:31* @Version 1.0*/public class StaticInnerClass {private StaticInnerClass(){}​public static StaticInnerClass getInstance(){return InnerClass.STATIC_INNER_CLASS;}​public static class InnerClass {private static final StaticInnerClass STATIC_INNER_CLASS = new StaticInnerClass();}}​

1.5 枚举

 package com.study.singleton;​import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;​/*** @ClassName SingleEnum* @Description enum本身也是一个class类,jdk 1.5就有了* @Author Jiangnan Cui* @Date 2023/3/20 23:18* @Version 1.0*/public enum SingleEnum {INSTANCE;public SingleEnum getInstance(){return INSTANCE;}}​class Test{public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {SingleEnum instance1 = SingleEnum.INSTANCE;Constructor<SingleEnum> declaredConstructor = SingleEnum.class.getDeclaredConstructor(String.class, int.class);//注意此处并不是无参构造方法,实际有String、int两个参数,要通过反编译工具jad.exe才能验证declaredConstructor.setAccessible(true);//        SingleEnum instance2 = SingleEnum.INSTANCE;SingleEnum instance2 = declaredConstructor.newInstance();System.out.println("instance1 = " + instance1);System.out.println("instance2 = " + instance2);​}}​// Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objectsat java.lang.reflect.Constructor.newInstance(Constructor.java:417)at com.study.singleton.Test.main(SingleEnum.java:26)​

javap -p 类名.class反编译: 

 jad.exe反编译结果:

 

待完善

普通话学习