当前位置: 首页 > news >正文

知道却做不到

这种“知道步骤但写不出来”的情况非常常见,核心原因是对“类的参数设计”和“类之间的协作关系”还没有形成清晰的逻辑链。其实参数设计有明确的规律——每个类的参数都应该服务于它的“核心职责”。我们用“从职责倒推参数”的方法,一步步帮你落地这两个类的设计。

第一步:明确每个类的“核心职责”(先想清楚“它要干什么”)

在这个场景中:

  1. Account的核心职责:
    管理账户余额的变动(存款),并保证多线程操作时的安全性。
    → 通俗说:“它是个银行账户,要能存钱、能查余额,还得防着多人同时瞎改余额”。

  2. AddMoneyThread的核心职责:
    作为线程,执行“给指定账户存指定金额”的任务。
    → 通俗说:“它是个办事员,要知道去哪个银行账户(Account)存多少钱(金额)”。

第二步:从职责倒推每个类需要的参数(再想“需要什么才能完成职责”)

参数的本质是“类完成职责所必需的外部信息”,缺了这些信息,类就无法工作。

1. Account 类需要哪些参数?

它的职责是“管理余额+保证安全”,需要的信息:

  • 初始余额:账户刚创建时,余额是多少?(比如默认0元,但也可以让用户指定)。
    → 所以 __init__ 方法可以加一个可选参数 initial_balance,默认值0。
  • 线程锁:为了多线程安全,需要内置一个锁(这个是类内部自己创建的,不需要外部传入,所以不算参数)。

因此 Account 类的参数设计:

class Account:def __init__(self, initial_balance=0):  # 可选参数:初始余额,默认0self._balance = initial_balance  # 用初始余额初始化self._lock = threading.Lock()  # 内部创建锁,不用外部传

它的方法(deposit)需要什么参数?
deposit 的职责是“存多少钱”,所以必须知道“存入金额”:

def deposit(self, money):  # 必需参数:要存入的金额self._lock.acquire()try:self._balance += moneyfinally:self._lock.release()

2. AddMoneyThread 类需要哪些参数?

它的职责是“作为线程给指定账户存指定金额”,需要的信息:

  • 要操作的账户:必须知道是给哪个 Account 实例存钱(没有账户,存哪里?)。
  • 要存的金额:必须知道每次存多少钱(没有金额,存多少?)。

这两个信息都需要外部提供(线程自己无法生成),所以必须作为参数传入 __init__ 方法。

因此 AddMoneyThread 类的参数设计:

class AddMoneyThread(Thread):def __init__(self, account, money):  # 两个必需参数:账户实例、存入金额super().__init__()  # 必须调用父类Thread的初始化self._account = account  # 保存账户实例(后面要用它调用deposit)self._money = money  # 保存存入金额(后面要传给deposit)

它的 run 方法需要参数吗?
不需要。因为 run 是线程启动后自动执行的,它的逻辑是固定的:“用保存的账户和金额,调用 deposit 方法”:

def run(self):self._account.deposit(self._money)  # 直接用实例属性,不用额外传参

第三步:主函数如何调用?(把类串联起来)

主函数的任务是“创建100个线程给同一个账户各存1元”,步骤:

  1. 创建一个 Account 实例(用默认初始余额0)。
  2. 循环100次,每次创建 AddMoneyThread 实例时,传入:
    • 同一个 Account 实例(所有线程操作同一个账户);
    • 金额1(每次存1元)。
  3. 启动所有线程,等待全部完成后,打印余额。

完整代码:

关键规律:参数设计的“必要性原则”

判断一个参数是否需要存在,就问自己:
“没有这个参数,这个类还能完成它的核心职责吗?”

  • Account 类没有 initial_balance 可以(用默认0),但 deposit 没有 money 就不行(不知道存多少)。
  • AddMoneyThread 类没有 account 不行(不知道存到哪),没有 money 也不行(不知道存多少)。

按照这个原则,你就能清晰地确定每个类需要哪些参数了。刚开始写不出来很正常,多按照“职责→参数→方法”的逻辑链练习几次,很快就能掌握这种设计思路。

http://www.hskmm.com/?act=detail&tid=25653

相关文章:

  • 题解:loj154 集合划分计数
  • 为什么 Java 中打印Object类型的变量无需强转,而从Object类型的数组中取元素却要强转?
  • WinReanimator恶意软件清除指南:详细步骤与工具使用
  • 251006
  • 2025国庆Day5
  • 字节跳动开源图标库:2000+图标一键换肤的魔法 - 教程
  • 换根DP学习笔记
  • 自动化数据操作平台获3000万美元融资
  • 模块
  • 实用指南:【相机基础知识与物体检测】更新中
  • AtCoder Beginner Contest 422 游记(VP)
  • 详细介绍:无人机光纤FC接口模块技术分析
  • 2025 --【J+S 二十连测】-- 第十三套 总结
  • 文件提供的基本操作
  • 深入解析:MySQL(50)如何使用UNSIGNED属性?
  • 迈向人机价值共生文明:AI元人文范式下的演化架构与协同治理
  • 10.6
  • 文件存储空间管理
  • 详细介绍:关于ios点击分享自动复制到粘贴板的问题
  • 新一代数据平台替代传统大数据技术栈
  • 攻击者如何绕过macOS内置安全防护机制
  • 在A列连续且相等行的最后插入空行,并求和
  • 10.6集训改错
  • @Prometheus 监控-MySQL (Mysqld Exporter) - 教程
  • AI元人文:走向人机价值共生的文明新范式
  • 实用指南:【机器学习基础】机器学习入门核心算法:层次聚类算法(AGNES算法和 DIANA算法)
  • CSP-J 第二轮集训 :总结 + 专题细分精讲_from_黄老师
  • ROIR 2024
  • 软件工程第一次随笔 - Nicholas
  • 深入解析:【数据库】关系数据库标准语言-SQL(金仓)下