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

Java面试第十三山!《设计模式》

    大家好,我是陈一。如果文章对你有帮助,请留下一个宝贵的三连哦~ 万分感谢!

一、设计模式入门指南

1. 什么是设计模式?

设计模式是可复用的解决方案模板,用于解决软件开发中常见的架构问题。如同建筑领域的经典设计图纸,它们经历了数十年的实践验证。

2. 为什么要学习?

  • 面试必考:90%的中高级Java面试涉及设计模式

  • 代码质量:减少重复代码,提升扩展性

  • 团队协作:提供统一的术语体系

  • 架构思维:培养面向对象设计能力

二、七大核心模式深度解析

1. 单例模式(Singleton)

定义:确保类只有一个实例,并提供全局访问点
场景:数据库连接池、日志记录器、配置管理

/**
 * 双重校验锁单例实现
 * 1. volatile防止指令重排序
 * 2. 双重检查保证线程安全
 */
public class DatabasePool {
    private static volatile DatabasePool instance;
    
    // 私有构造器防止外部实例化
    private DatabasePool() {
        // 初始化数据库连接
    }
    
    public static DatabasePool getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (DatabasePool.class) {
                if (instance == null) { // 第二次检查
                    instance = new DatabasePool();
                }
            }
        }
        return instance;
    }
}

适用场景对比表

实现方式线程安全延迟加载序列化安全
饿汉式
双重检查锁
静态内部类
Enum实现

2. 工厂模式(Factory)

定义:将对象创建逻辑封装,客户端不直接实例化对象
场景:支付渠道选择、日志记录器切换

// 抽象产品接口
interface PaymentGateway {
    void processPayment(BigDecimal amount);
}

// 具体产品实现
class Alipay implements PaymentGateway {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("支付宝支付:" + amount);
    }
}

class WechatPay implements PaymentGateway {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("微信支付:" + amount);
    }
}

// 工厂类
public class PaymentFactory {
    public static PaymentGateway createGateway(String type) {
        switch (type.toUpperCase()) {
            case "ALIPAY":
                return new Alipay();
            case "WECHAT":
                return new WechatPay();
            default:
                throw new IllegalArgumentException("不支持的支付类型");
        }
    }
}

3. 观察者模式(Observer)

定义:定义对象间的一对多依赖关系,当一个对象状态改变时自动通知依赖对象
场景:订单状态通知、股票价格变动提醒

// 主题接口
interface OrderSubject {
    void registerObserver(OrderObserver o);
    void notifyObservers();
}

// 具体主题(被观察者)
class Order implements OrderSubject {
    private List<OrderObserver> observers = new ArrayList<>();
    private String status;

    public void setStatus(String status) {
        this.status = status;
        notifyObservers();
    }

    @Override
    public void registerObserver(OrderObserver o) {
        observers.add(o);
    }

    @Override
    public void notifyObservers() {
        observers.forEach(o -> o.update(this.status));
    }
}

// 观察者接口
interface OrderObserver {
    void update(String status);
}

// 具体观察者
class SMSNotifier implements OrderObserver {
    @Override
    public void update(String status) {
        System.out.println("短信通知:订单状态变更为 " + status);
    }
}

4. 装饰器模式(Decorator)

定义:动态地为对象添加额外职责,比继承更灵活
场景:数据流处理、IO增强

// 基础组件接口
interface Coffee {
    String getDescription();
    BigDecimal getCost();
}

// 具体组件
class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "普通咖啡";
    }

    @Override
    public BigDecimal getCost() {
        return new BigDecimal("15.00");
    }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription() + " + 牛奶";
    }

    @Override
    public BigDecimal getCost() {
        return decoratedCoffee.getCost().add(new BigDecimal("3.00"));
    }
}

5. 策略模式(Strategy)

定义:定义算法族,使它们可以互相替换
场景:促销活动计算、排序算法切换

// 策略接口
interface DiscountStrategy {
    BigDecimal applyDiscount(BigDecimal originalPrice);
}

// 具体策略实现
class FullReductionStrategy implements DiscountStrategy {
    @Override
    public BigDecimal applyDiscount(BigDecimal price) {
        return price.compareTo(new BigDecimal("100")) > 0 
               ? price.subtract(new BigDecimal("20")) 
               : price;
    }
}

class PercentageDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal applyDiscount(BigDecimal price) {
        return price.multiply(new BigDecimal("0.8"));
    }
}

// 上下文类
class ShoppingCart {
    private DiscountStrategy strategy;

    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public BigDecimal checkout(BigDecimal total) {
        return strategy.applyDiscount(total);
    }
}

6. 代理模式(Proxy)

定义:为其他对象提供代理以控制对这个对象的访问
场景:延迟加载、访问控制、日志记录

interface Image {
    void display();
}

class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("加载图片: " + filename);
    }

    @Override
    public void display() {
        System.out.println("显示图片: " + filename);
    }
}

class ImageProxy implements Image {
    private RealImage realImage;
    private String filename;

    public ImageProxy(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

7. 责任链模式(Chain of Responsibility)

定义:将请求的发送者和接收者解耦,使多个对象都有机会处理请求
场景:审批流程、异常处理链

abstract class Approver {
    protected Approver nextApprover;

    public void setNext(Approver approver) {
        this.nextApprover = approver;
    }

    public abstract void processRequest(PurchaseRequest request);
}

class Manager extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount().compareTo(new BigDecimal("1000")) < 0) {
            System.out.println("经理审批通过:" + request);
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

class Director extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount().compareTo(new BigDecimal("5000")) < 0) {
            System.out.println("总监审批通过:" + request);
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

三、设计模式对比速查表

模式类型适用场景关键特征
单例模式创建型全局唯一实例私有构造、静态实例
工厂模式创建型复杂对象创建封装实例化逻辑
观察者模式行为型事件通知系统发布-订阅机制
装饰器模式结构型动态功能扩展包装器嵌套
策略模式行为型算法灵活切换接口多实现
代理模式结构型访问控制/功能增强间接访问
责任链模式行为型多级处理流程链式传递

四、高频面试问题集锦

1. Spring框架中的设计模式应用

  • 工厂模式:BeanFactory

  • 代理模式:AOP实现

  • 模板方法:JdbcTemplate

  • 适配器模式:HandlerAdapter

2. 单例模式双重检查锁原理

if (instance == null) {                  // 第一次检查
    synchronized (Singleton.class) {     // 同步锁
        if (instance == null) {          // 第二次检查
            instance = new Singleton();  // 安全初始化
        }
    }
}

关键点:volatile防止指令重排序 + 双重检查减少锁竞争

3. 装饰器模式 vs 继承

维度装饰器模式继承
扩展方式运行时动态组合编译时静态绑定
灵活性可多层嵌套不同功能单一父类限制
类数量按需组合,避免类爆炸容易产生大量子类

五、实战应用技巧

  1. 模式组合:观察者+责任链实现多级审批

  2. 避免滥用:简单场景不要过度设计

  3. 重构识别:当发现多重条件判断时考虑策略模式

  4. 性能考量:代理模式会增加调用层级

真实案例:某电商系统使用装饰器模式实现多级优惠叠加

BigDecimal total = new BigDecimal("200");
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);    // +3元
coffee = new SugarDecorator(coffee);   // +1元
System.out.println("总价:" + coffee.getCost()); // 输出19.00

六、学习资源推荐

  1. 书籍

    • 《Head First设计模式》(图文并茂)

    • 《设计模式:可复用面向对象软件的基础》(GoF经典)

  2. 在线资源

    • Refactoring.Guru(交互式教程)

    • Java Design Patterns(官网示例)

  3. 实战训练

    • 阅读Spring框架源码

    • 重构现有项目代码

掌握设计模式的关键在于理解思想而非死记硬背。建议从简单模式入手,结合项目实际需求逐步应用。记住:没有最好的模式,只有最合适的场景


翻过这座山,他们就会听到你的故事!转发本文给需要的朋友,一起备战金三银四! 🚀


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

相关文章:

  • 快速部署Samba共享服务器作为k8s后端存储
  • Android adb调试应用程序
  • 解锁应急管理新境界:AR眼镜与指挥平台的完美融合
  • 常见框架漏洞:Thinkphp(TP)篇
  • 【Git流程最佳实践】 开发较大功能时应使用project branch
  • WordPress二次开发中常用到的一些变量和函数
  • [C++面试] 你了解transform吗?
  • 嵌入式驱动开发方向的基础强化学习计划
  • fuctioncall使用经验
  • QA:备份产品的存储架构采用集中式和分布式的优劣?
  • ai-by-hand-excel: 用 Excel 手搓各种 AI 算法和模型
  • 大型语言模型(LLM)推理框架的全面分析与选型指南(2025年版)
  • 【深度学习】Self-Attention机制详解:Transformer的核心引擎
  • LeetCode 942 增减字符串匹配
  • UE4学习笔记 FPS游戏制作15修正可以换枪中可以继续换枪和开火的Bug
  • 【Rust】一文掌握 Rust 的详细用法(Rust 备忘清单)
  • Leetcode 刷题笔记 图论part05
  • Cocos Creator Shader入门实战(六):使用setProperty动态设置材质属性,以及材质常用接口
  • 解决了使用ElementUI日期选择器时,选择“2024第1周”这一特殊时间段所触发的change事件返回时间的特殊情况处理问题。
  • L2-005 集合相似度