【问题标题】:using Composite Pattern to count the number of people in the world使用复合模式计算世界上的人数
【发布时间】:2018-01-09 17:33:02
【问题描述】:

我正在尝试制作一个复合模式,计算世界、大陆、州的人数......对不起,没有州,但国家,我很抱歉

这是我遵循的模式:

我这样做了:

但我不确定它是否正确,因为我可以使用leaf -> population 吗?

因为当我为 PC 做复合模式时,它(PC= PC 的组件将是机柜 = 复合,机柜将是 HDD = 叶和主板 = 复合,从主板将是 RAM = 叶和 CPU = 叶)。我想说的是每片叶子都是不同的,在我的图表中是相同的。

你认为我至少有一些好东西。

感谢您的回答:)

【问题讨论】:

  • 您的概括(继承)完全错误。子类的目标是扩展父类功能。也许Area 而不是顶部的WorldState 也不是 那种 Continent 等等。
  • 你不应该从叶子开始,这样做时你应该从世界->人口开始
  • 我不知道你的PC复合材料长什么样,但你描述的它看起来也不好。您可以从一个类似设备的类开始,它可以包含更多设备,每个设备都可以由电路、机械装置......组成。所以你有你的设备 PC,它由 HDD、BlueRay、主板、电源设备组成。并且这些设备中的每一个都可以包含更多的设备或 curciuts....

标签: design-patterns uml diagram composite


【解决方案1】:

首先,您应该先分析您的问题。那么你有什么以及它是如何相关的。所以你有一个 大陆组成的世界,每个大陆 国家组成>,其中每个国家 地区组成。在进行这样的 OO 分析时,名词(此处以粗体标记)是您的类的候选者。并且关系术语给出了一些指示类是如何相关的(标记为斜体)。

那么我们可以看到什么?有一些术语(称为实体)具有一些直接排序的层次包含关系。但是没有任何关系可以将某物视为另一种类型的元素。这是考虑如何相互继承时的重要信息;由于继承关系可以看作是一种特殊化,所以在这里没有任何意义:一个国家不是一个特定的世界,一个世界也不是一个特定的国家。此外,我们看到没有绕过,例如一个国家不是世界的直接部分。并且任何元素都不能包含自己类型的元素,例如没有国家包含国家。

那么我们可以从这个简短的分析中学到什么?如果不改变显着的表达性(例如更改预期的层次结构)或不引入更多额外的复杂性(例如通过约束),我们就无法将问题表述为复合问题。

现在在第二步中,我们根据分析结果开发设计。设计最终的样子取决于对元素的处理方式。

  1. 解决方案:在您的示例中,您可以将 calculatePopulation 操作添加到任何类。由于任何类都知道它的部分和它们的类型,这可以通过调用下一个元素类型的包含实例的 calculatePopulation 操作直接完成。这将是解决此类问题的 OO 方式,如果没有进一步的限制,这很可能是最好的方式。

要启动它,您只需调用 wold 实例的 calculatePopulation。

如果你想以统一的方式对待任何一种元素,你可以创建一个抽象类或接口,让所有元素继承/实现它。此类/接口声明了 calculatePopulation 操作。有了这个改进的解决方案,您可以从层次结构中的任意元素开始计算人口,而无需关心它是什么类型的元素。

  1. 解决方案:当您想要一个未在类层次结构内部实现且是递归的算法时。在这种情况下,您需要一个抽象,以便您可以以相同的方式处理所有元素,因为算法实现不应关注太多细节。因此,还让所有元素都从一个抽象类继承,该类具有提供包含元素的操作和提供人口的操作,人口直接是元素的一部分(不像之前的情况那样是传递/间接的)。所以现在你会遇到两个明显不同的情况,首先你有子元素并且没有直接人口,其次,你没有子元素和直接人口。但是您的遍历可以忽略这一点。

在这里,您首先调用您的实现(这是另一个类)并传递您想要填充的对象。

当然,还有其他解决方案。但是所有那些只为这个问题使用复合的人都是非常人为的,因为它的概念是递归的,你的问题不是递归的(即没有元素可以包含相同类型的元素),因此复合是不可分割的或者让我们称之为超大。

【讨论】:

  • 我还给了其他答案一些 cmets。
【解决方案2】:

至少你不需要拥有 World、Continent、State、Region。

只有具有可能属性类型的组合才能知道这是大陆、州还是地区。

状态应该是叶子吗?

像文件树一样思考:层数没有定义,模式支持任何深度数。

在 State 上,您会得到一个方法 getPopulation,它在 Component 中也被定义为抽象,在 Composite 中定义为返回 -1 或无限(一个值表示未实现)。

对我来说,在叶子和组件上也需要 getChild 方法。没有它,就不可能实现递归算法来导航复合。

在叶子上,它返回一个空列表:这是知道到达叶子的方法。

PS:我离开聚合是因为它在你的第一个图表中使用,如果我这样做,我会使用简单的关联或组合,而不是聚合。

【讨论】:

  • 我知道我写的是什么州,但我的意思是国家,那么我还能用什么叶子呢?
  • @Dolis 如果您只需要 Country 作为叶子,请不要按国家/地区更改州。如果您需要将 State 和 Country 作为叶子,请按 Leaf(或更有意义的完整词)更改 State,并添加可能值为 State 或 Country 的属性类型(例如 Composite)
  • 我猜你需要一个约束。否则,您可以创建 StateWorlds。理论上这是可能的。但现实世界不允许这样做。
  • @kilian 你确定吗?这取决于用于 Composite 的枚举和用于叶子的枚举,id State no ?
  • 建议的解决方案不是很好,因为您现在需要根据分配的枚举区分大小写。通过使用不同的类可以很容易地忽略它。通过使用两种不同的类型概念,首先将状态作为类,将所有其他元素作为使用枚举的泛型类型,这会使情况变得更糟。
猜你喜欢
  • 1970-01-01
  • 2013-01-04
  • 2015-09-18
  • 2020-02-04
  • 2020-07-29
  • 1970-01-01
  • 2012-08-14
  • 2021-05-15
  • 2021-04-01
相关资源
最近更新 更多