面试漫谈(十四)- 设计模式篇

Posted by YiBo on December 22, 2020

前记

这个问题真的是从小问到大,但一直也没答好

说说你知道的设计模式

  • 责任链模式

    定义一个接口,然后有多个实现方式,netty中的pipeline,或者是拦截器

  • 适配器模式

    把一个类的接口转换为另一个所期待的接口,从而使俩个不匹配的类一起工作

  • 模板模式

  • 工厂模式

    采用工厂方法代替new操作的一种模式

    Spring IOC创建bean的过程,Spring中无论是通过xml配置还是配置类还是注解类进行创建bean

    如果之间调用的话,会很耦合

  • 单例模式

    • 双检查锁

    • 静态内部类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      public class SingleTon{
      	private SingleTon{}
      	private static class SingleTonHolder{
      		private static SingleTon INSTANCE = new SingleTon();
      	}
      	public static SingleTon getInstance(){
      		return SingleTonHolder.INSTANCE;
      	}
      }
      

      外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。不仅能保证线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化

      1. 如何保证线程安全

        类加载时机:JAVA虚拟机在有且仅有的5种场景下会进行类的初始化:

        • 遇到 new getStatic setStatic 或者 invokeStatic 这4个字节码指令时。对应的java场景为:new ,读取或者设置一个静态字段时,调用一个类的静态方法时
        • 使用 java.lang.reflect 包的方法对类进行反射调用
        • 当初始化一个类时,如果其父类还未进行初始化。。
        • 当虚拟机启动时,用户需要指定一个要执行的主类(main()方法)
        • 使用JDK1.7,如果一个 java.lang.invoke.MethodHandle实例最后的解析结果….

        以上五种都是主动引用。

        静态内部类属于被动引用

        不管多少个线程去调用getInstance()方法,取的都是统一而instance对象,而不用重新创建。当getInstance()方法被调用时,SingleTonHolder才在SingleTon的运行时常量池里,把符号引用替换为直接引用,这时静态对象instance也真正被创建。—–虚拟机会保证一个类方法在多线程环境中被正确的加锁,同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的方法,其他线程都需要阻塞等待。同一个加载器下,一个类型只会初始化一次

      2. 缺点:传参问题

    • 枚举单例

      1
      2
      3
      4
      5
      6
      
      public enum SingleTon{
      	INSTANCE:
      		public void method(){
          		
      		}
      }
      

      通过 SingleTon.INSTANE

  • 代理模式

    Spring AOP 日志打印 异常处理 事务控制 权限控制

  • 建造者模式

    将一个复杂的对象构建与它的标识分离。与工厂模式的区别:建造者模式更加关注与零件装配的顺序。java中StringBuilder就是建造者模式创建的

  • 外观模式

    也叫门面模式,隐藏系统的复杂性,向客户端提供了一个客户端可以访问系统的接口

  • 策略模式

    简化if else带来的复杂性