java面向对象设计原则是解决实际问题的思维工具:封装需嵌入业务规则而非仅隐藏字段;继承应让位于组合,以提升灵活性与可测性;开闭原则强调通过抽象接口支持扩展而不修改原代码;依赖倒置要求模块间依赖抽象而非具体实现。

Java面向对象设计原则不是纸面上的教条,而是解决实际问题的一套思维工具。真正落地的关键,在于理解每条原则要应对什么痛点,并在写类、定义接口、组织方法时主动做判断。
封装:保护不变量,而不是隐藏字段
很多人把封装等同于“private + getter/setter”,结果只是把字段锁起来,却放任外部随意修改内部状态。真正的封装,是把业务规则嵌进对象行为里。
- 余额不能为负,就不要暴露setBalance(),而是提供withdraw(amount),并在方法内校验
- 订单状态有流转约束(比如“已支付”不能直接退回到“待付款”),就把状态变更逻辑封装在transitionTo(newState)中,而不是让调用方直接赋值
- 返回集合时避免暴露可变引用,用Collections.unmodifiableList()或返回不可变对象
继承与组合:优先组合,只在需要多态时用继承
继承容易导致类层次臃肿、耦合加深。组合更灵活,也更容易测试和替换。
- 一个OrderProcessor类,不需要继承PaymentHandler,而是持有PaymentService接口的实例
- 当需要扩展支付方式(支付宝、微信、银行卡)时,只需新增实现类,不改动处理器本身
- 如果发现子类大量重写父类方法,或者出现“菱形继承”结构,基本说明该用组合替代了
开闭原则:对扩展开放,对修改关闭
核心是把可能变化的部分抽象成接口或策略,让新增功能不碰原有代码。
- 优惠计算逻辑经常变?定义DiscountCalculator接口,每种规则(满减、折扣、积分抵扣)各自实现
- 日志输出目标可能从文件切到Kafka?把日志行为抽成Logger接口,运行时注入不同实现
- 关键点在于:新增一种折扣方式,只需要加一个类+注册到上下文,不用改OrderService里的if-else分支
依赖倒置:依赖抽象,不依赖具体实现
不是“高层模块不依赖低层模块”,而是“双方都依赖抽象”。这决定了你如何定义接口、怎么注入依赖。
- DAO层不应直接依赖MySQL驱动,而应依赖UserRepository接口;Service层调用它,不关心底层是JDBC还是MyBatis
- Spring的@Autowired能生效,前提是你的字段类型是接口,不是具体类
- 测试时,可以轻松用内存Map实现替换真实数据库操作,因为依赖的是契约,不是实现细节
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











