设计原则
字数: 0 字 时长: 0 分钟
在有了一定的编程经历之后,特别是工作中对大量功能模块代码重构的经历,越来越认识到良好的设计有利于软件的可读性、健壮性和可维护性。项目模块代码规模较小可以选择推翻重来,如果涉及代码规模较大,甚至涉及到多个团队共同维护的模块,在后期维护扩展时往往会花费大量的成本去弥补初期的不良设计。
因此,有必要系统学习设计模式相关知识,提升编码架构设计能力和阅读源码的能力。
1. 单一职责原则
一个类,只干一件事,只处理一个独立的功能领域。
java
// 违反单一职责的案例:报表生成器承担双重职责
class ReportGenerator {
public void fetchDataFromDB() { ... } // 职责1: 数据获取
public void formatToPDF() { ... } // 职责2: 格式转换
// 重构为:
// DataFetcher 类负责数据获取
// PdfFormatter 类负责格式转换
}
2. 开闭原则
对扩展开放,对修改关闭。当我们新增功能时,新增代码即可,而不必去修改已有的类或方法。这一点,我深有体验,在工作中很多时候新增功能时都需要改动已有的类或方法,有时候往往需要测试对已有功能是否有影响,加大风险,不利于维护。
3. 里氏替换原则
子类必须能够完全替代其基类而不会破坏原有系统功能。也就是继承关系不能乱用,继承不是为了代码复用,而是为了保持通用的行为,如需代码复用可以选择组合的方式。
4. 接口隔离原则
客户端不应被迫依赖其不需要的方法。也就是接口只定义足够且必要的方法,如果定义的太多,实现类也不得不实现这些根本不需要的方法。
5. 依赖倒置原则
高层模块不应该依赖底层模块,二者都应该依赖抽象。也就是面向接口编程,而不是具体的实现。
java
// 违规:直接依赖具体类
class OrderService {
private MySQLOrderDao dao = new MySQLOrderDao();
}
// 合规:依赖抽象
class OrderService {
private final OrderDao dao; // 接口依赖
public OrderService(OrderDao dao) {
this.dao = dao;
}
}
6. 迪米特法则
只与直接相关的类交流,尽量减少对外部对象内部细节的依赖。《Effective Java》 中作者提到了,区分一个组件设计得好不好,唯一重要的因素在于,它对外部的其他组件而言,是否隐藏了其内部数据和实现细节。这就是封装,有利于解耦。
java
// 违规方案:跨越多个对象层级,暴露不必要的细节
user.getAccount().getBalance().format();
// 合规方案:通过封装减少依赖链
user.getFormattedBalance(); // User内部处理格式化逻辑
7. KISS 保持简单
KISS (Keep it Stupid Simple),保持简单,避免过度设计。这条原则应该是最难的,需要根据实际情况把握设计考量:
- 在开发非核心场景,比如某个临时场景(比如仅仅为了应付某次特殊上线需求)时可以采取这条原则
- 开发核心场景时(比如支付模块)优先采取前
6
条设计原则,保持一个良好的架构设计