我会有 Fisherman、FishingRod、FishingLine、Pond、Fish 和“天空”(或“环境”)。
在面向对象的领域,对象通常最终会比你想象的更聪明。渔夫“有”(包含)FishingRod。他将 FishingLine(FishingRod 的一个组件)投射到 Pond 中。池塘“观察”天空以确定是白天还是黑夜,然后掷骰子以确定是否应该将鱼放在线上。
改变的对象层次结构是 FishingLine 可以选择性地包含 Fish,并由 FishingRod 拥有,FishingRod 由 Fisherman 拥有。 Pond 包含 Fish,接收 FishingLines 但不“拥有”它们,也知道但不拥有天空。
随后的方法类似于以下内容:
Fisherman.FishingRod - 一个初始化属性(或一对 getter/setter 方法),用于给 Fisherman 一个 FishingRod 到 FishAt() 一个 Pond。这是可选的;渔夫可以创建自己的钓鱼竿,或者他自己可以从钓鱼竿集合中选择它,而不是给他钓鱼竿。
Fisherman.FishAt(Pond) - 告诉渔夫使用他的 FishingRod 来 Launch() 将 FishingLine 放入池塘,然后 Retrieve() 它可能会得到一条鱼。
FishingRod.Launch(Pond) - 将 FishingRod 的 FishingLine 释放到池塘中。
FishingRod.Retrieve() - 从池塘中检索钓鱼线,返回一条鱼,它也可能什么都没有。
Pond.StockWith(Fish[]) - 给渔夫用鱼竿钓到的池塘鱼。请记住,在 OO-land 中,所有东西要么得到它想要的东西,要么知道如何制造它;如果这是您想要遵循的模型,Pond 可以很容易地创建 Fish,但是这里的用户故事没有说明这是如何发生的(通常意味着它超出了故事的范围)。
Pond.SetFishingLine(FishingLine) - 被 FishingRod 用来将其 FishingLine 放入池塘中。这就是融合了业务逻辑的“驱动功能”。调用此函数时,池塘应询问天空是否是白天,并可能根据一天中给定时间的机会将一条鱼放在钓鱼线上。
Sky.IsDay() - 如果是白天则返回 true,如果是晚上则返回 false。
如果您认为 Pond 不应该直接知道将 Fish 放在 FishingLine 上的确切规则,它可以将 FishingLine 及其 Fish[] 提供给所谓的“纯虚构”。这种制造,“钓鱼逻辑”,将是检查天空并应用规则的制造。在开发中,这通常是一件好事,因为这意味着 FishingLogic 可以在不改变 Pond 的情况下改变,除非 FishingLogic 需要更多来自 Pond 的信息(比如水温)。
各种对象代表现实生活中的各种基本“模式”:
- Fisherman 是一个“演员”,与我们的用户最接近。像这样的系统的用户基本上站在演员的肩膀上,告诉他该做什么。
- FishingRod 是“助手”或“实用程序”。它是“工具”的真实模拟,包含状态和业务逻辑的混合体,可帮助它执行非常具体的任务。
- 此模型中的FishingLine 类似于“请求”或“命令”。它的唯一目的是从一个对象传递给另一个对象,当这种情况发生时,它表明接收者应该采取特定的行动。
- 鱼是一种“反应”;对请求的答复。可能有,也可能没有。
- Pond 是一个“存储库”;它包含事物,并根据一组逻辑处理外部对象对这些事物的请求。
- Sky 是一个“状态桶”。它拥有数据,并通过其接口提供对该数据的访问。
- FishingLogic 是“纯虚构”;它与我们正在建模的现实世界中的“名词”(对象)没有类似物,并且存在以包含环境规则或在模型对象不必知道如何发生的情况下发生的事情(鱼如何决定上钩?)