Java模块化:如何让系统像乐高一样自由拼装?JPMS+设计模式全解析(附代码)

一、传统系统的「死亡陷阱」

1.1 无序耦合:像在玩「俄罗斯方块」
// 传统代码示例:  
public class UserService {  
    public void register(User user) {  
        // 直接调用数据库类  
        Database.insert(user);  
        // 直接调用邮件服务  
        EmailService.sendWelcome(user.email);  
    }  
}  

程序员的血泪史
“我改个数据库逻辑,结果邮件服务爆炸!
代码像『多米诺骨牌』,改一处全崩!”


1.2 维护噩梦:像在修「千年古董」

需求:添加一个支付模块
结果

  • 支付类需要依赖数据库
  • 数据库类需要依赖日志模块
  • 日志模块需要依赖配置中心

    最终:
    java.lang.NoClassDefFoundError 报错到天亮!

二、模块化设计的「三把利剑」

2.1 JPMS:给Java装个「模块化大脑」

Java Platform Module System (JPMS) 是Java 9的「模块化超能力」,
就像给代码装了个「乐高说明书」,
自动说:“这个模块需要哪些依赖?我来帮你管理!”

模块化实战步骤

// 1. 创建模块声明文件 module-info.java  
module com.example.user {  
    requires java.sql; // 引入数据库模块  
    requires com.example.common; // 引入公共模块  
    exports com.example.user.service; // 对外暴露Service包  
    opens com.example.user.entity; // 对外开放实体类  
}  

// 2. 模块化启动类:  
public class ModularApp {  
    public static void main(String[] args) {  
        // 只能访问声明的模块  
        UserModule userModule = new UserModule();  
        userModule.start();  
    }  
}  

代码注释小课堂
requires 是「我要用这些模块」,
exports 是「这些类可以被外部使用」,
模块间像「乐高积木」一样精准对接!


2.2 依赖倒置:给模块装个「防抖开关」

依赖倒置原则(DIP)

“高层模块不直接依赖低层模块,
两者都依赖抽象接口。”

代码示例:数据库抽象层

// 抽象接口:  
public interface Database {  
    void insert(User user); // 低层实现  
}  

// 高层模块:  
public class UserService {  
    private final Database database; // 依赖抽象接口  

    public UserService(Database database) {  
        this.database = database;  
    }  

    public void register(User user) {  
        database.insert(user); // 通过接口调用  
    }  
}  

// 实现类:  
public class MySQLDatabase implements Database {  
    public void insert(User user) {  
        // 具体实现  
    }  
}  

灵魂拷问
为什么不用直接调用?
因为程序员的代码要「可替换」!
想换到PostgreSQL?改一行代码搞定!


2.3 接口隔离:给模块穿个「隐身衣」

接口隔离原则(ISP)

“不要强迫模块实现不需要的接口,
要像『乐高积木』一样只暴露必要接口。”

代码示例:支付模块优化

// 传统接口:  
public interface PaymentService {  
    void payByCreditCard(); // 信用卡支付  
    void payByAlipay();     // 支付宝支付  
    void payByWechat();     // 微信支付  
}  

// 优化后:  
public interface CreditCardPayment {  
    void pay(); // 只暴露必要接口  
}  

public interface AlipayPayment {  
    void pay();  
}  

public class PaymentService {  
    private final CreditCardPayment creditCard;  
    private final AlipayPayment alipay;  

    public PaymentService(CreditCardPayment creditCard, AlipayPayment alipay) {  
        this.creditCard = creditCard;  
        this.alipay = alipay;  
    }  
}  

程序员的哲学
这段代码像在说:
“我只暴露需要的接口,
你不需要的『按钮』我直接藏起来!”


三、设计模式:模块化的「瑞士军刀」

3.1 适配器模式:给模块装个「翻译器」
// 适配器模式示例:  
public class LegacyDatabaseAdapter implements NewDatabaseAPI {  
    private final LegacyDatabase legacyDB;  

    public LegacyDatabaseAdapter(LegacyDatabase legacyDB) {  
        this.legacyDB = legacyDB;  
    }  

    @Override  
    public void insert(User user) {  
        // 将新接口调用转换为旧系统  
        legacyDB.save(user);  
    }  
}  

程序员的冷笑话
为什么适配器模式最受欢迎?
因为它让新旧系统「和平共处」!


3.2 工厂模式:给模块造个「生产流水线」
// 工厂模式示例:  
public class ModuleFactory {  
    public static Database createDatabase() {  
        if (isMySQL()) return new MySQLDatabase();  
        else return new PostgreSQLDatabase();  
    }  

    private static boolean isMySQL() {  
        // 根据配置判断  
        return true;  
    }  
}  

灵魂拷问
为什么工厂模式像「造车流水线」?
因为它负责「生产」所有模块实例!


四、实战案例:用模块化拯救「千年古董系统」

4.1 场景:电商系统突然「耦合爆炸」

需求:新增一个「优惠券模块」,
但发现它需要:

  • 依赖用户模块
  • 依赖订单模块
  • 依赖支付模块

    最终:
    CircularDependencyException 报错到天亮!
4.2 解决方案:模块化+设计模式组合拳
// 模块划分:  
module com.example.coupon {  
    requires com.example.user; // 只需要用户模块  
    requires com.example.order; // 只需要订单模块  
    exports com.example.coupon.service; // 对外暴露接口  
}  

// 优惠券服务类:  
public class CouponService {  
    private final UserService userService; // 依赖抽象接口  
    private final OrderService orderService;  

    public CouponService(UserService userService, OrderService orderService) {  
        this.userService = userService;  
        this.orderService = orderService;  
    }  

    public void applyCoupon(User user, Order order) {  
        // 业务逻辑  
    }  
}  

事后复盘
这波操作让系统耦合度降低70%,
新增模块时间从3天缩短到3小时,
老板直接夸我:「你的模块化比我的咖啡还提神!」


五、防坑指南:避免模块化的「四大天坑」

5.1 坑位1:直接硬编码,像「用锤子修表」

反例:在Service类中直接 new Database()
正确姿势:用依赖注入+工厂模式

5.2 坑位2:模块间直接互相引用,像「打结的毛线」

反例:模块A引用模块B,模块B又引用模块A
正确姿势:用接口隔离+工厂模式


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值