设计模式面试题精选

设计模式是软件设计经验的总结,面试中常考察单例、工厂、策略、观察者等模式的原理和应用场景。

1. 单例模式的实现方式?

  • 饿汉式:类加载时初始化,线程安全。缺点:可能浪费资源。
  • 懒汉式(双重检查锁):volatile + synchronized实现懒加载和线程安全。
  • 静态内部类:利用类加载机制保证线程安全,推荐写法。
  • 枚举:天然防反射和序列化攻击,《Effective Java》推荐。

双重检查锁示例:volatile防止指令重排序(new对象不是原子操作:分配内存→初始化→引用赋值)。

2. 工厂模式的三种形式?

  • 简单工厂:一个工厂类根据参数创建不同产品。违反开闭原则(新增产品需改工厂)。
  • 工厂方法:每个产品对应一个工厂类,符合开闭原则。类数量过多。
  • 抽象工厂:创建一组相关产品(产品族)。如DatabaseFactory同时创建Connection和Statement。

Spring中的工厂模式:BeanFactory是简单工厂,FactoryBean是工厂方法。

3. 策略模式的应用场景?

策略模式将算法封装为独立类,使算法可互相替换,避免大量if-else。

  • 支付方式:支付宝、微信、银行卡等不同支付策略。
  • 排序算法:快速排序、归并排序等策略选择。
  • 促销折扣:满减、打折、直减等促销策略。

JDK中的Collections.sort()传入Comparator就是策略模式。Spring的Resource接口也是策略模式的应用。

4. 观察者模式原理及应用?

观察者模式定义了一对多的依赖关系,当主题状态变化时所有观察者收到通知。

  • 角色:Subject(主题)/Observable、Observer(观察者)。
  • Java实现:java.util.Observable和Observer接口(已废弃)。
  • Spring事件:ApplicationEvent + ApplicationListener + ApplicationEventPublisher。
  • 消息队列:发布/订阅模型本质是观察者模式的分布式实现。
  • MVC:Model是Subject,View是Observer。

5. 代理模式:静态代理 vs JDK动态代理 vs CGLIB?

  • 静态代理:手动编写代理类,实现相同接口。一个接口一个代理类,麻烦。
  • JDK动态代理:基于接口,通过Proxy.newProxyInstance()生成代理类。传入InvocationHandler处理逻辑。目标类必须实现接口。
  • CGLIB:基于继承,通过字节码技术生成目标类的子类。不能代理final类/方法。比JDK代理快。

Spring AOP:目标类实现接口用JDK代理,否则用CGLIB。可通过@Aspect注解定义切面。

6. 模板方法模式?

模板方法在父类定义算法骨架,将某些步骤延迟到子类实现,不改变算法结构即可重定义步骤。

  • AbstractList:get()、size()由子类实现,indexOf()在父类定义。
  • HttpServlet:service()调用doGet()、doPost()等,由子类实现。
  • Spring:JdbcTemplate、RestTemplate都使用模板方法模式。
  • AbstractApplicationContext:refresh()定义IOC流程,子类实现customizeBeanFactory()等。

7. 责任链模式?

责任链模式将请求沿着处理者链传递,每个处理者决定处理或传递给下一个。

  • Servlet Filter:FilterChain串联多个Filter,请求依次经过。
  • Spring Interceptor:HandlerInterceptor的preHandle/postExecute链式调用。
  • Netty Pipeline:ChannelHandler链式处理IO事件。
  • Sentinel:ProcessorSlotChain处理限流、熔断等。

8. 装饰器模式 vs 代理模式?

两者结构相似但意图不同:

  • 装饰器:增强对象功能,关注对象本身。如IO流:BufferedInputStream装饰FileInputStream。
  • 代理:控制对象访问,关注访问控制。如远程代理、虚拟代理、保护代理。
  • 区别:装饰器通常由客户端组装,代理通常由框架创建。

9. 适配器模式?

适配器模式将不兼容接口的类适配为期望接口。

  • 类适配器:继承被适配类,实现目标接口。
  • 对象适配器:持有被适配类的引用,实现目标接口。更灵活。
  • JDK示例:InputStreamReader适配InputStream为Reader。
  • Spring MVC:HandlerAdapter适配不同类型的Controller。

10. 设计模式六大原则?

  • 单一职责原则(SRP):一个类只有一个引起变化的原因。
  • 开闭原则(OCP):对扩展开放,对修改关闭。
  • 里氏替换原则(LSP):子类必须能替换父类。
  • 依赖倒置原则(DIP):依赖抽象,不依赖具体。
  • 接口隔离原则(ISP):客户端不应依赖不需要的接口。
  • 迪米特法则(LoD):最少知道原则,降低耦合。

By admin

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注