设计思想
软件设计的目标是构建「易维护、易扩展、易理解」的系统。这不是靠感觉,而是有一套经过验证的指导思想。本节介绍几个最核心的设计原则。
三个经典原则
DRY — Don't Repeat Yourself
不要重复你自己
同样的逻辑只写一次。如果你在两个地方看到几乎相同的代码,就应该考虑合并。
java
// ❌ 重复:两处验证逻辑一模一样
class UserValidator {
public void validateUsername(String username) {
if (username == null || username.isBlank()) {
throw new IllegalArgumentException("用户名不能为空");
}
if (username.length() < 3) {
throw new IllegalArgumentException("用户名至少3个字符");
}
}
public void validateEmail(String email) {
if (email == null || email.isBlank()) {
throw new IllegalArgumentException("邮箱不能为空");
}
if (email.length() < 3) { // 这段重复了!
throw new IllegalArgumentException("邮箱至少3个字符");
}
}
}
// ✅ 提取公共验证方法
class StringValidator {
public static void requireNonBlank(String value, String fieldName) {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException(fieldName + "不能为空");
}
}
public static void requireMinLength(String value, int minLength, String fieldName) {
if (value != null && value.length() < minLength) {
throw new IllegalArgumentException(fieldName + "至少" + minLength + "个字符");
}
}
}DRY 不是「不能有重复代码」那么简单。真正的 DRY 是意图不重复,而不是「字符完全相同」。两处恰好相似的代码未必需要合并,但两处做同样事情的代码必须合并。
KISS — Keep It Simple, Stupid
保持简单,笨蛋
复杂的解决方案往往源于对问题的理解不够透彻。好的设计应该是简单的。
java
// ❌ 过度设计:为了「可扩展」引入不必要的抽象
interface Processor<T> {
Result process(T input);
}
abstract class AbstractProcessor<T> implements Processor<T> {
protected abstract Result doProcess(T input);
public final Result process(T input) {
return doProcess(input);
}
}
class StringProcessor extends AbstractProcessor<String> {
@Override
protected Result doProcess(String input) {
return new Result(input.toUpperCase());
}
}
// ✅ 够用就好:直接解决问题
class StringProcessor {
public String process(String input) {
return input.toUpperCase();
}
}KISS 不是让你写烂代码。是在你设计一个可能有三个抽象层的系统之前,问问自己:「我真的需要这些吗?」
YAGNI — You Aren't Gonna Need It
你不会需要它的
不要为你认为以后可能需要的功能提前写代码。你对「未来需求」的预测往往是错的。
java
// ❌ YAGNI 反面:猜测未来需要多种支付方式
class PaymentService {
public void payWithAlipay(Order order) { }
public void payWithWechat(Order order) { }
public void payWithPaypal(Order order) { }
public void payWithCreditCard(Order order) { }
public void payWithBankTransfer(Order order) { }
// ... 一堆现在用不到的方法
}
// ✅ YAGNI 正面:只实现现在需要的
class PaymentService {
public void pay(Order order, PaymentMethod method) {
// 根据传入的支付方式处理
// 未来新支付方式?到时候再加
}
}YAGNI 和 KISS 相辅相成。YAGNI 让你不要过度设计,KISS 让你把必须做的事做简单。
高内聚,低耦合
这是软件设计的终极目标。
内聚衡量一个模块内部各部分联系的紧密程度。高内聚意味着一个类只做一件事,把相关的东西放在一起。
耦合衡量不同模块之间的依赖程度。低耦合意味着类与类之间的联系尽可能少。
高内聚 + 低耦合 → 理想状态
↓
类内部:职责单一,紧密相关
类之间:依赖最小,仅通过接口交流一个实际的例子:
java
// ❌ 低内聚 + 高耦合:OrderService 做了太多事,还依赖具体实现
class BadOrderService {
private MySQLOrderRepository repo; // 耦合具体实现
private SendGridEmailSender sender; // 耦合具体实现
private StripePaymentGateway gateway; // 耦合具体实现
public void createOrder(Order order) {
// 验证、计算、保存、发邮件全在这里
// 超过 200 行...
}
}
// ✅ 高内聚 + 低耦合:每个类各司其职,通过接口交流
interface OrderRepository {
void save(Order order);
}
interface NotificationService {
void notify(Order order);
}
interface PaymentGateway {
PaymentResult pay(Order order);
}
class OrderService {
private final OrderRepository repository;
private final NotificationService notifier;
private final PaymentGateway paymentGateway;
public OrderService(OrderRepository repository,
NotificationService notifier,
PaymentGateway paymentGateway) {
this.repository = repository;
this.notifier = notifier;
this.paymentGateway = paymentGateway;
}
public void createOrder(Order order) {
// 逻辑清晰,依赖注入,测试友好
}
}SOLID 原则
设计原则有很多,SOLID 是最核心的五个。如果只能记住一套原则,就记住它。
详细内容请查看 五大原则(SOLID)。
总结
DRY → 消除重复
KISS → 保持简单
YAGNI → 不要超前
高内聚 → 类内职责单一
低耦合 → 类间依赖最小
SOLID → 面向对象设计的核心原则这些原则不是教条,而是思考工具。面对设计决策时,用这些原则帮助判断,而不是盲目套用。
最好的代码是那些不需要注释就能读懂的代码。做到这一点,设计就不会太差。
