【问题标题】:How to conceptually add polymorphism?如何在概念上添加多态性?
【发布时间】:2015-11-13 13:19:42
【问题描述】:

我有一个小组项目,其中涉及使用一个用于模拟冰淇淋店的 Java 程序并将其转换为 GUI 应用程序。

商店预装了 16 种不同的冰淇淋。店里有工人,也有收银员和存货员(都是从工人身上延伸出来的,收银员有耐心,存货员有耐心)。

工人(以及收银员/库存员)能够提供冰淇淋。只有收银员可以处理订单,只有库存员可以补货冰淇淋(每个冰淇淋从 80 勺开始)。

在给定时间只有一名活跃的收银员/存货员,并且可能有一名正在休息的收银员/存货员。工人从一个文件(每行明确说明它是工人、库存员还是收银员)加载到它们各自的数组列表中(其中有一个 ArrayList 用于 Workers,一个 ArrayList 用于Stockers 和收银员的 ArrayList)。

我现在发现将其转换为 GUI 非常复杂,不得不处理 3 个 ArrayList。我想更改项目以将所有工作人员保存到一个 Worker 类型的 ArrayList 中。但是,商店中的许多操作已经在假设三个不同的 ArrayList 的情况下定义/执行。

更改代码以将整个 Worker 文件加载到一个 Worker 类型的 ArrayList 中很简单。但是,如何从概念上更改商店的其余功能以使用一个 ArrayList?

例如 - 如果我想将商店的活跃收银员设置为 Bill,我如何导航 ArrayList 以仅查找收银员,然后找到 Bill,然后将他设置为活跃?

我想我很困惑的是如何与子类的 ArrayList 交互并知道在给定时间我正在与哪种类型的子类交互?我知道如何使用 instanceOf(),但我觉得它比这更进一步(没有双关语)?

【问题讨论】:

  • 一般来说,如果您必须检查特定类型,那么设计中的多态性可能会被破坏。这违反了里氏替换原则。当您调用所有模型共有的操作时,模型本身应该知道它需要做什么。例如,如果“Bill”需要开始他的轮班,那么您会在集合中找到 Name 等于 "Bill" 的元素,并会调用对该对象的操作,例如 beginWorking()。对象本身应该包含它需要做什么的逻辑。
  • 所以 - 假设我的 Workers ArrayList 看起来像(其中字母表示类的类型,Worker/Stocker/Cashier):[W, S, S, W, C, C]。如果我开始商店并想将活动收银员/库存商设置为它们在 ArrayList 中的第一个实例(因此在库存商的索引 1 和收银员的索引 4 处) - 后来我按下一个按钮以“更改活动收银员/库存商” - 我怎样才能显示除活跃的收银员/库存员之外的所有收银员/存货员?
  • 对你的代码有零知识,我真的不能说你会如何展示任何东西。如果我有一个 Employee 对象的集合,我想我也会有一个对象来协调他们当前的工作时间表。也许称为 TimeClock 对象或具有语义性质的东西。它将保持当前班次的状态,并知道哪些员工当前在哪里工作。 ArrayList 实际上只是 Employee 对象的存储库,仅此而已。你从中获取一个 Employee 。它不应该用于协调班次和其他业务逻辑。

标签: java arraylist polymorphism


【解决方案1】:

当您想要调用通用 Worker 操作(如 getPaid() 或 startShift())时,通常会遍历一组 Worker。这些的实现可能会根据特定的类而有所不同(本质上是多态),但它们对所有Workers 都是通用的。

如果不查看您的代码,您似乎不太可能从 Worker 集合中调用 Cashier 或 Stocker 特定方法中受益。

【讨论】:

    【解决方案2】:

    我认为将它们全部放在一个集合中会比保留单独的列表更成问题。

    正如您所提到的,找到一种特定类型会很“麻烦”。

    如果您有很多其他需要迭代所有工作人员的情况,请考虑将它们全部保存在一个额外的集合中,或者创建一个迭代所有三个列表的方法,您可以重复使用。

    【讨论】:

      【解决方案3】:

      你可以这样做

      private void processCashiers(){    
          List<Cashier> cashiers = new ArrayList<>();
              for(Worker w : workers){
                  if(w instanceof Cashier){
                      cashiers.add(w);
                  }
              }
          // do something with cashierers here
      }
      

      基本上是在本地创建一个指定的列表并进行处理。

      【讨论】:

        【解决方案4】:

        听起来更容易将它们作为工作类型的不同数组/对象进行管理,而另一个对象将它们作为雇员进行管理。雇员不是一个数组,而是一个包含指向所有不同数组的指针的对象,但也可以处理高级任务,并以通用方式在 GUI 上显示它们。显示它们将按类型分组,除非您需要按其他标准(从文件排序)显示它们,在这种情况下您可以返回一个(临时?)数组。如果您在 GUI 上具有灵活性,请制作可以处理特定于该对象类型的任何内容的工作类型视图/子视图。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-24
          相关资源
          最近更新 更多