当前位置: 首页 > article >正文

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 objects
     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
     at com.study.singleton.Test.main(SingleEnum.java:26)
 ​

javap -p 类名.class反编译: 

 jad.exe反编译结果:

 

待完善


http://www.kler.cn/a/2333.html

相关文章:

  • 【spring-cloud-gateway总结】
  • Docker_常用命令详解
  • 中国量子计算机领域的发展现状与展望
  • 靜態IP與DHCP的區別和用法
  • 任务三数据库加固
  • 图书馆管理系统(三)基于jquery、ajax
  • Linux第一个小程序git三板斧
  • 【28】Verilog进阶 - RAM的实现
  • JAVA开发(自研项目的开发与推广)
  • BeanPostProcessor原理分析
  • Flutter内阴影
  • 人脸识别经典网络-MTCNN(含Python源码实现)
  • 深度学习(22):如何判断训练过程中深度学习模型损失值不再下降
  • Java语言-----类与对象的秘密
  • vue2和vue3中路由的区别和写法?
  • Django(一)安装
  • 计算机网络(第十二弹) --- 传统访问过程与 CDN 访问过程对比
  • 【华为OD机试真题JAVA】水仙花数问题
  • 数据仓库相关面试题
  • Ubuntu安装rancher2.6的k8s集群手册
  • 程序员必须知道的HTML常用代码有哪些?
  • Oracle中含有recover 状态的数据文件环境中,做异机恢复
  • CSS 实现六边形柱状图
  • MySQL注入秘籍【绕过篇】
  • 【Java Spring基本问题】记录面试题宝典中自己不熟悉的Spring问题
  • Java现在好找工作吗?