设计模式在Java日常开发中的实战

VIP/

设计模式是“空中楼阁”?聊聊在Java日常开发中的高频实战

设计模式并非大厂专属,它们就藏在每一次合理的代码封装与解耦之中。

一、 前言:模式,源于反复出现的问题

提起设计模式,很多开发者会立刻想到《设计模式:可复用面向对象软件的基础》这本经典著作中那23种模式,感觉高深莫测,似乎只在框架源码或架构设计中才会出现。
然而,事实恰恰相反。设计模式的本质,是前辈程序员对特定场景下通用解决方案的总结和命名。你在日常编码中,很可能已经在不自觉地使用它们。今天,我们就来盘点那些在Java业务开发中出场率极高、能显著提升代码质量的设计模式及其实战场景。

二、 高频实战模式详解

1. 单例模式 (Singleton) – 全局唯一的管家

模式简介:确保一个类只有一个实例,并提供一个全局访问点。
实战场景:这是使用最广泛的模式之一。常用于管理共享资源,避免重复创建带来的开销或不一致。
  • 数据库连接池​ (如HikariCP的DataSource)
  • 配置信息管理器​ (全局的配置对象)
  • 日志记录器
  • Spring框架中,默认的Bean作用域就是单例。
示例代码 (双重检查锁定,线程安全)
public class ConfigManager {
    private static volatile ConfigManager instance;
    private Properties configs;

    private ConfigManager() { loadConfigs(); } // 私有构造

    public static ConfigManager getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (ConfigManager.class) {
                if (instance == null) { // 第二次检查
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }
    // 使用:ConfigManager.getInstance().getProperty("key");
}
注意:在Spring管理的项目中,通常直接使用@Component@Service注解创建单例Bean,无需手动实现。

2. 工厂模式 (Factory) – 对象的“创建专家”

模式简介:定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
实战场景解除对象创建与具体使用的耦合。当你无法预知需要创建哪种具体对象,或创建过程复杂时,就用它。
  • 连接器创建:根据配置(MySQL、Oracle)创建不同的数据库连接对象。
  • 解析器生成:根据文件后缀(.json, .xml)选择不同的解析器。
  • 支付集成:根据用户选择(微信、支付宝、银联)实例化不同的支付策略客户端。
示例代码 (简单工厂)
public interface Parser {
    Object parse(String data);
}

public class JsonParser implements Parser { /* 实现 */ }
public class XmlParser implements Parser { /* 实现 */ }

public class ParserFactory {
    public static Parser getParser(String type) {
        switch (type.toLowerCase()) {
            case "json": return new JsonParser();
            case "xml":  return new XmlParser();
            default: throw new IllegalArgumentException("Unsupported type");
        }
    }
}
// 使用:Parser parser = ParserFactory.getParser("json");

3. 建造者模式 (Builder) – 构造复杂对象的利器

模式简介:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
实战场景:解决构造方法参数过多(“伸缩构造器模式”难以阅读和维护)或对象属性之间存在复杂约束的问题。
  • 构建复杂的AlertDialog(Android)。
  • 构建一个包含数十个可选参数的查询条件对象(QueryParam)。
  • 构建邮件对象(发件人、收件人、主题、正文、附件等)。
示例代码 (Lombok版)
// 传统方式:User user = new User(1L, "张三", null, "北京", "13800138000", 1 ...); // 灾难!
// 建造者模式:
@Builder
@Data
public class UserDTO {
    private Long id;
    private String name;
    @Builder.Default
    private Integer status = 0; // 设置默认值
    private String address;
    // ... 更多属性
}
// 使用:清晰、灵活、可读性极强
UserDTO user = UserDTO.builder()
                     .id(1L)
                     .name("张三")
                     .address("北京")
                     .build();

4. 适配器模式 (Adapter) – 兼容的“转换插头”

模式简介:将一个类的接口转换成客户期望的另一个接口。使原本接口不兼容的类可以一起工作。
实战场景对接、集成与兼容。在引入新库、新组件,或进行系统重构时,它是“救火队员”。
  • 第三方SDK集成:新支付接口与老系统接口不匹配,编写一个适配器类来转换。
  • 日志框架统一:项目中原有Log4j的API,想平滑迁移到SLF4J,可以使用适配器。
  • JDBC驱动就是适配器模式的经典体现,它适配了不同数据库与统一的JDBC接口。
示例代码
// 目标接口:我们系统期望的充电接口
interface USBC { void chargeWithUSB(); }

// 被适配者:现有的、不兼容的类
class TypeC { void chargeWithTypeC() { System.out.println("Type-C充电"); } }

// 适配器
class TypeCToUSBCAdapter implements USBC {
    private TypeC typeC;
    public TypeCToUSBCAdapter(TypeC typeC) { this.typeC = typeC; }
    @Override
    public void chargeWithUSB() {
        System.out.print("通过适配器:");
        typeC.chargeWithTypeC(); // 调用被适配者的方法
    }
}
// 使用:USBC charger = new TypeCToUSBCAdapter(new TypeC());

5. 观察者模式 (Observer) – 事件驱动的核心

模式简介:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
实战场景实现松耦合的事件处理机制。一个对象的变化需要通知其他多个对象,且它不知道具体是谁。
  • GUI事件监听(如Java Swing中的ActionListener)。
  • 消息队列的发布-订阅模型
  • Spring的事件驱动模型ApplicationEventApplicationListener
  • 业务中:用户注册成功,需要同时发送欢迎邮件、发放新手优惠券、初始化个人空间。
示例代码 (简化版)
// 观察者接口
interface EventListener { void onEvent(String event); }

// 被观察者 (主题)
class UserService {
    private List<EventListener> listeners = new ArrayList<>();
    public void addListener(EventListener listener) { listeners.add(listener); }
    public void register(String username) {
        // ... 注册逻辑
        System.out.println("用户" + username + "注册成功");
        // 通知所有观察者
        listeners.forEach(listener -> listener.onEvent("USER_REGISTERED"));
    }
}
// 使用:
UserService service = new UserService();
service.addListener(event -> {
    if ("USER_REGISTERED".equals(event)) {
        System.out.println("【邮件服务】发送欢迎邮件");
    }
});
service.register("张三");

6. 策略模式 (Strategy) – 自由切换的算法族

模式简介:定义一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式让算法独立于使用它的客户而变化。
实战场景消除冗长的if-else或switch-case,尤其是当它们根据不同的类型或条件执行不同的行为时。
  • 支付方式:微信支付、支付宝支付、信用卡支付,它们都是“支付”这个策略的不同实现。
  • 折扣计算:满减折扣、百分比折扣、会员折扣。
  • 数据验证规则:手机号验证、邮箱验证、身份证验证。
示例代码
interface DiscountStrategy {
    double applyDiscount(double originalPrice);
}
class VIPDiscount implements DiscountStrategy {
    @Override public double applyDiscount(double price) { return price * 0.8; }
}
class FullReductionDiscount implements DiscountStrategy {
    @Override public double applyDiscount(double price) { return price >= 100 ? price - 20 : price; }
}
class PaymentContext {
    private DiscountStrategy strategy;
    public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; }
    public double checkout(double price) { return strategy.applyDiscount(price); }
}
// 使用:优雅地替换算法
PaymentContext ctx = new PaymentContext();
ctx.setStrategy(new VIPDiscount());
double finalPrice = ctx.checkout(200.0);

7. 模板方法模式 (Template Method) – 定义算法的骨架

模式简介:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
实战场景流程固定,部分步骤可变的场景。用于消除重复代码,实现代码复用。
  • JdbcTemplate:Spring JDBC中的JdbcTemplate定义了执行SQL的流程(获取连接、创建语句、执行、处理结果集、关闭资源),而由开发者通过RowMapper回调接口来实现如何映射每一行数据。
  • 工作流审批:提交申请 -> 各级审批 -> 归档。审批流程固定,但每一级的审批人逻辑不同。
  • 一个抽象类定义sendRequest()的流程:准备参数 -> 签名 -> 发送HTTP请求 -> 处理响应。子类只需实现准备参数处理响应这两个抽象方法。
示例代码
public abstract class DataExporter {
    // 模板方法:定义了固定的导出流程
    public final void export() {
        prepareData();
        doExport();
        onComplete();
    }
    protected abstract void prepareData(); // 子类实现
    private void doExport() { System.out.println("执行通用导出逻辑..."); }
    protected void onComplete() { System.out.println("导出完成。"); } // 可选钩子
}
public class UserExporter extends DataExporter {
    @Override
    protected void prepareData() { System.out.println("准备用户数据..."); }
}

三、 如何学习与应用:心法大于招式

  1. 理解意图,而非死记结构:问自己,这个模式解决了什么痛点?它的核心思想是什么(如解耦、扩展、复用)?
  2. 从小处着手:下次在写一个超过3个参数的构造器时,想想建造者模式;下次遇到一长串if-else判断不同行为时,想想策略模式。
  3. 阅读优秀源码:Spring、MyBatis、Guava、JDK等优秀库和框架中,设计模式的应用随处可见。这是最好的学习材料。
  4. 避免过度设计不要为了用模式而用模式。在简单场景下(比如只会有一个if-else),直接写可能更清晰。模式的引入应是为了应对实际或可预见的复杂性。

四、 总结

设计模式不是银弹,而是经过实战检验的、用来管理代码复杂性的工具箱。熟练掌握并在日常开发中灵活运用这些高频模式(单例、工厂、建造者、适配器、观察者、策略、模板方法),能让你写出更清晰、更灵活、更易维护的代码。
记住,我们的目标不是成为“模式高手”,而是成为能写出“好代码”的工程师。当你能自然而然地选择最合适的工具(模式)来解决手头的问题时,你就已经领悟了设计模式的精髓。

购买须知/免责声明
1.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
2.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
3.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
4.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
5.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
6.不保证任何源码框架的完整性。
7.侵权联系邮箱:188773464@qq.com
8.若您最终确认购买,则视为您100%认同并接受以上所述全部内容。

海外源码网 后端编程 设计模式在Java日常开发中的实战 https://moyy.us/22107.html

上一篇:

已经没有上一篇了!

相关文章

猜你喜欢