Java设计模式实战:高频场景解析与避坑指南

引言

设计模式是软件开发的基石,但许多开发者面对23种模式时容易陷入“学完就忘”或“滥用模式”的困境。本文从工业级项目视角出发,精选 10种高频设计模式,结合真实代码案例与主流框架应用,帮你建立模式思维,拒绝纸上谈兵。


一、创建型模式:告别new的暴力美学

1. 工厂方法模式(Factory Method)
  • 核心痛点:对象创建逻辑散落各处,难以统一管理。
  • 场景案例:电商平台需要支持多种支付方式(支付宝、微信、银联)。
  • 代码实现
    interface Payment {
        void pay(double amount);
    }
    class Alipay implements Payment { /* 支付宝实现 */ }
    class WechatPay implements Payment { /* 微信支付实现 */ }
    
    // 抽象工厂
    interface PaymentFactory {
        Payment createPayment();
    }
    // 具体工厂
    class AlipayFactory implements PaymentFactory {
        public Payment createPayment() { return new Alipay(); }
    }
    
  • 框架应用:Spring的BeanFactory通过XML/注解配置创建Bean。
2. 建造者模式(Builder)
  • 核心痛点:构造器参数爆炸(如HTTP请求配置包含20个可选参数)。
  • 场景案例:配置复杂的数据库连接池。
  • 代码实现
    public class DataSourceConfig {
        private final String url;
        private final int maxConn;
        // 私有构造器
        private DataSourceConfig(Builder builder) {
            this.url = builder.url;
            this.maxConn = builder.maxConn;
        }
        // 建造者
        public static class Builder {
            private String url = "jdbc:mysql://localhost:3306/test";
            private int maxConn = 100;
            public Builder url(String url) { this.url = url; return this; }
            public DataSourceConfig build() { return new DataSourceConfig(this); }
        }
    }
    // 使用
    DataSourceConfig config = new DataSourceConfig.Builder()
                                    .url("jdbc:mysql://prod:3306/app")
                                    .build();
    
  • 框架应用:OkHttp的Request.Builder构建复杂HTTP请求。

二、结构型模式:让代码如乐高般灵活组合

3. 代理模式(Proxy)
  • 核心痛点:直接访问敏感资源导致安全隐患。
  • 场景案例:数据库查询添加缓存层。
  • 代码实现
    interface Database {
        String query(String sql);
    }
    // 真实对象
    class RealDatabase implements Database {
        public String query(String sql) { /* 执行真实查询 */ }
    }
    // 代理对象(添加缓存)
    class DatabaseProxy implements Database {
        private RealDatabase realDB;
        private Map<String, String> cache = new HashMap<>();
        public String query(String sql) {
            if (cache.containsKey(sql)) return cache.get(sql);
            String result = realDB.query(sql);
            cache.put(sql, result);
            return result;
        }
    }
    
  • 框架应用:Spring AOP通过动态代理实现事务管理。
4. 适配器模式(Adapter)
  • 核心痛点:老旧系统接口不兼容。
  • 场景案例:集成第三方旧版支付SDK。
  • 代码实现
    // 旧版支付类(不兼容接口)
    class LegacyPayment {
        public void payInDollars(double amount) { /* 美元支付逻辑 */ }
    }
    // 新版支付接口
    interface PaymentGateway {
        void pay(double amount, String currency);
    }
    // 适配器
    class PaymentAdapter implements PaymentGateway {
        private LegacyPayment legacyPayment;
        public PaymentAdapter(LegacyPayment payment) {
            this.legacyPayment = payment;
        }
        public void pay(double amount, String currency) {
            if ("USD".equals(currency)) {
                legacyPayment.payInDollars(amount);
            } else {
                throw new UnsupportedOperationException("Unsupported currency");
            }
        }
    }
    
  • 框架应用:Spring MVC的HandlerAdapter兼容多种Controller类型。

三、行为型模式:让对象协作更优雅

5. 观察者模式(Observer)
  • 核心痛点:模块间硬编码调用导致耦合。
  • 场景案例:订单状态变更触发库存更新和短信通知。
  • 代码实现
    // 被观察者
    class OrderService {
        private List<OrderListener> listeners = new ArrayList<>();
        public void addListener(OrderListener listener) {
            listeners.add(listener);
        }
        public void completeOrder(Order order) {
            // 订单完成逻辑
            listeners.forEach(listener -> listener.onOrderCompleted(order));
        }
    }
    // 观察者
    class InventoryService implements OrderListener {
        public void onOrderCompleted(Order order) {
            updateStock(order.getItems()); // 更新库存
        }
    }
    class SmsService implements OrderListener {
        public void onOrderCompleted(Order order) {
            sendSms(order.getUser()); // 发送短信
        }
    }
    
  • 框架应用:Spring的事件机制(ApplicationEventPublisher)。
6. 策略模式(Strategy)
  • 核心痛点:if-else分支处理多种算法变体。
  • 场景案例:多种数据加密算法动态切换。
  • 代码实现
    interface EncryptionStrategy {
        String encrypt(String data);
    }
    class AESStrategy implements EncryptionStrategy { /* AES加密 */ }
    class RSAStrategy implements EncryptionStrategy { /* RSA加密 */ }
    
    class EncryptionContext {
        private EncryptionStrategy strategy;
        public void setStrategy(EncryptionStrategy strategy) {
            this.strategy = strategy;
        }
        public String executeEncrypt(String data) {
            return strategy.encrypt(data);
        }
    }
    
  • 框架应用:Java的Comparator实现多种排序策略。

四、工业级应用与陷阱规避

1. 框架中的模式典范
框架 设计模式 应用场景
Spring 工厂模式、代理模式 Bean创建、AOP实现
MyBatis 建造者模式 SqlSessionFactory构建
Netty 责任链模式 Pipeline处理器链
2. 常见陷阱与解决方案
  • 陷阱1:单例模式线程安全问题

    • 错误示例:非线程安全的懒汉式单例。
    • 解决方案:双重检查锁 + volatile关键字。
  • 陷阱2:过度使用装饰器模式

    • 错误示例:嵌套5层装饰器导致调试困难。
    • 解决方案:优先使用组合替代多层装饰。

五、模式速查表:按场景精准匹配

问题场景 推荐模式 解决重点
需要统一管理对象创建 工厂方法 解耦创建逻辑
构造复杂对象 建造者 参数灵活组合
整合不兼容接口 适配器 无缝兼容旧系统
添加访问控制/缓存 代理 间接访问资源
事件通知/状态更新 观察者 解耦发布-订阅关系
动态切换算法 策略 消除if-else分支
多级审批流程 责任链 灵活扩展处理节点

六、学习路线与效率提升

  1. 三步学习法

    • 第一步:通过《Head First设计模式》理解基础概念。
    • 第二步:在Spring/MyBatis源码中寻找模式应用(如Spring的BeanFactory)。
    • 第三步:在项目中实践重构(如用策略模式替换支付逻辑的if-else)。
  2. 效率工具推荐

    • IDEA插件
      • SequenceDiagram:自动生成调用序列图。
      • Code Iris:可视化代码依赖关系。
    • 调试工具:Arthas在线诊断Java应用。

结论:模式是脚手架,不是枷锁

设计模式的终极目标不是写出“符合模式”的代码,而是解决实际问题。记住以下原则:

  • 先有问题,再有模式:不要为了模式而模式。
  • 适度重构:在代码腐化前及时应用模式优化。
  • 理解优于记忆:掌握模式背后的设计思想(如开闭原则、依赖倒置)。

当你下次看到混乱的代码时,不妨自问:这里的问题本质是什么?哪种模式能以最小成本解决? 这才是设计模式的真正价值。

你可能感兴趣的:(笔记,学习,java,设计模式)