别再请求数据!掌握“Tell, Don't Ask”原则

发布: (2025年12月19日 GMT+8 08:57)
3 min read
原文: Dev.to

Source: Dev.to

介绍

在面向对象编程(OOP)中,最常见的错误之一是把对象当作普通的数据结构来使用。我们经常把对象的数据取出来,进行一些逻辑处理,然后再把结果放回去。本文阐述了 Tell, Don’t Ask(TDA) 原则,并通过一个简单的 ShopAccount 示例展示它如何提升代码质量。

Tell, Don’t Ask 原则

  • Don’t Ask:不要向对象请求数据再自行进行逻辑处理。
  • Tell:告诉对象该做什么,让它自行处理自己的状态。

遵循 TDA 能提升 封装性内聚性

反模式示例

Shop 类在处理本应属于 Account 的逻辑,违反了封装。

package com.mateandgit.programming.chapter1_2.problem;

public class Shop {

    public void sell(Account account, Product product) {
        // ❌ BAD: Asking for data (getMoney)
        long price = product.getPrice();
        long mileage = account.getMoney();

        // ❌ BAD: The Shop decides if the account has enough money
        if (mileage >= price) {
            // ❌ BAD: Modifying the account's state externally
            account.setMoney(mileage - price);
            System.out.println(product.getName() + " purchased.");
        } else {
            System.out.println("Insufficient balance.");
        }
    }
}

问题

  • 封装性破坏Shop 知道 Account 的内部细节(money 字段以及余额的计算方式)。
  • 逻辑重复 – 任何其他需要扣款的类都必须重复 if (balance >= price) 的检查。
  • 难以维护 – 一旦验证规则改变(例如“最低余额必须保持 100”),所有访问 Account 的类都需要更新。

重构方案

将逻辑移到 Account 类中。Shop 现在只向 Account 发出指令。

package com.mateandgit.programming.chapter1_2.solution;

public class Shop {

    public void sell(Account account, Product product) {
        // ✅ GOOD: Ask a question (canAfford)
        if (account.canAfford(product.getPrice())) {

            // ✅ GOOD: Tell the object to do something (withdraw)
            account.withdraw(product.getPrice());
            System.out.println(product.getName() + " purchased.");
        } else {
            System.out.println("Insufficient balance.");
        }
    }
}

Account 类中,你会实现 canAfford()withdraw() 等方法来封装相应的逻辑。

重构的好处

  • 更好的封装Shop 不再了解取款的实现细节,只是发送一条消息。
  • 逻辑可复用 – 验证规则(canAfford)集中在 Account 中。
  • 可读性提升 – 代码读起来像一句话:“如果账户能负担,就取款”。
  • 更高的内聚性和更低的耦合度 – 对象自行管理状态,使代码更清晰、更易维护。

应用 Tell, Don’t Ask

  • 不要getSomething() → calculate → setSomething()
  • :在对象内部创建方法并 告诉 它执行相应操作。

结果:高内聚、低耦合,封装性更好。

Back to Blog

相关文章

阅读更多 »

Java 中的方法重写

什么是 method overriding?当子类为已经在 parent class 中定义的 method 提供特定实现时,这称为 method overriding。