【问题标题】:Java OO -- An object that provides a new way to interact with other objects? [closed]Java OO——提供与其他对象交互的新方法的对象? [关闭]
【发布时间】:2013-03-14 18:02:42
【问题描述】:

假设我有一个List<Apple> 对象,每个苹果都有一个颜色。

我实现了另一个对象,它的输入是苹果对象列表。我可能会在这个对象上实现一些功能,比如“让我知道青苹果的数量。”,我可以在不知道该对象的内部表示的情况下调用它。

你会怎么称呼这个人?这似乎是基本的 OO,但我在想一个描述性的名称时遇到了麻烦。

【问题讨论】:

  • 这个Object什么?如果它是一个篮子,那么Basket 就可以了。如果你有一个SchoolChild 并且你有一个Collection<SchoolChild> 的容器,那么可能是School。选择描述Object 角色的内容。
  • AppleSupervisor?园丁?苹果监督者?史蒂夫乔布斯?
  • 鲍勃叔叔建议不要使用“经理”、“处理器”等无意义的术语——我倾向于同意他的观点。
  • 用谷歌搜索“访客模式”。实现一个访问者。
  • “实用方法包”?我会将所有这些方法设为静态,并将其称为实用程序类。对于类名本身,它可以是AppleUtilitiesApples(基于JDK 中的标准ArraysCollections 类)。

标签: java terminology


【解决方案1】:

既然您在谈论List<Apple>,那么您可能也在谈论Collection<Apple>(列表继承集合)。

如果您想强调“收藏”,那么我将命名为“收藏”。苹果传统上以蒲式耳出售,但您不关心测量,所以我会使用更通用(不取决于大小)的术语“篮子”。

public class Basket {

   private int greenCount;

   public void addApple(Apple apple) {
     if (apple.isGreen()) {
        greenCount++;
     }
   }

   public int getGreenAppleCount() {
      return greenCount;
   }

}

这恰当地体现了计算篮子中青苹果的责任。

另一方面,实用程序似乎将任务的责任与特定类型绑定的对象分开。例如,让我们看一个假设的AppleCounterUtil

public class AppleCounterUtil {

    public int getCount(Collection<Apple> apples, AppleCondition condition) {
        int count = 0;
        for (Apple apple : apples) {
            if (condition.isSatisfied(apple)) {
               count++;
            }
        }
    }

}

现在我们有了一个不错的实用程序,它实际上并不维护计数,而是在每次需要时从可能不同的苹果列表中重新计算计数。

关键是后一个例子不是面向对象的,因为没有概念对象。声明没有对象的基本原理是因为包含该实用程序的类缺少状态。对象是数据密切相关的代码的集合。当您只有代码时,可以合理地论证您有一个名称空间函数而不是一个对象。

为了再次看到区别,让我们比较两个 sn-ps 的代码。使用我们的第一个“篮子”方法:

...
int greenOnes = basket.getGreenAppleCount();
basket.addApple(new GreenApple());
greenOnes = basket.getGreenAppleCount();
...

变得非常笨重,但由于我们是面向对象的,我们可以轻松地将Basket Listener 接口添加到Basket

public class Basket {

   public void addListener(BasketListner listener) {
     ...
   }

   public void addApple(Apple apple) {
     ...
     for (BasketListnener listner : listeners) {
       listener.appleAdded(this);
     }
   }

}

... some other class ... implements BasketListener {

   int greenOnes = 0;

   ...

   public void appleAdded(Basket basket) {
      greenOnes = basket.getGreenAppleCount();
   }
}

同时使用面向实用程序的技术

...
int greenOnes = AppleCounterUtil.getCount(apples, new GreenCountCondition());
apples.addApple(new GreenApple());
greenOnes = AppleCounterUtil.getCount(apples, new GreenCountCondition());
...

表面上看起来很相似,直到您尝试添加更多功能。在尝试添加“苹果列表监听器”时,您很快就会意识到AppleCounterUtil 不负责维护计数,并且无法被监听。 “苹果列表”也不负责维护计数,通用列表通常会提供错误的监听接口。

不幸的是,当一个人变得面向实用程序时,他们通常会尝试通过添加更多实用程序方法来解决问题。这最终可能意味着特定的关注点(谁管理苹果组)可以分布在许多实用程序中,而无需任何实用程序单独负责该任务。每个实用程序只提供一些可以按需计算的“功能”。

在某些情况下,按需计算功能可能会依赖于其他按需计算功能,这样您就可以在两者之间获得功能耦合(即使没有直接的代码耦合)。这种有效的耦合意味着如果您未能按顺序调用特定的一组实用程序,或者省略了所需的实用程序调用,您的代码就会中断。一个极端的情况是对象最终失去了它们的行为,以至于它们变成了数据结构,或者失去了通常与对象相关联的行为。它是一种面向对象的设计反模式,被称为“贫血对象”。

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    相关资源
    最近更新 更多