【问题标题】:Multiple instance of class versus array Java类的多个实例与数组 Java
【发布时间】:2016-09-04 09:44:22
【问题描述】:

我的问题是以下哪个示例代表正确的做法? 这些方法的优点和缺点是什么。 是否有另一种(正确的)方法来实现这一目标?

假设我有课

public class Person {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String print() {
        return this.name;
    }
}

类的用法如下:

public static void main(String[] args) {
        List<Person> people = new ArrayList<Person>();
        people.add(new Person("Jane Doe"));
        System.out.println(people.get(0).print());
}

然后是另一种方法:

public class Persons {

    private ArrayList<String> persons;

    public Persons() {
        persons = new ArrayList<String>();
    }

    public void putPerson(String name) {
         persons.add(name);
    }

    public String print(int id) {
        return this.persons.get(id);
    }
}

然后使用它:

public static void main(String[] args) {
        Persons persons = new Persons();
        persons.putPerson("John Doe");
        System.out.println(persons.print(0));
    }

编辑:

假设我有 10 000 个这样的人。 创建 10,000 个类实例有什么缺点吗?

【问题讨论】:

  • 您的实际问题是什么?自己收藏是对还是错? (在这种情况下,Persons 是一个只能包含 Person 对象的集合)
  • 制作这些系列有什么缺点吗?
  • @Evus 只要Person 有一个字段就可以了,尝试添加多个字段和不同的子类型。
  • 我认为这要么是基于选项的,要么更适合“程序员”网站。恕我直言,除非您 (a) 向 Persons 类添加更多专门的方法,或者 (b) 想要限制某些方法,例如删除个人,一个基本的(键入的)列表就足够了,并且最终更清晰。此外,您不必重新公开所有列表功能。
  • 我结束了问题。因为它可以是基于意见的,我的问题是不准确的。

标签: java oop


【解决方案1】:

我更喜欢第一种方式,因为很少需要创建一个包装类来保存一个集合(比如Persons -> Person)。如果将 Persons 类重命名为 Company/Community,这是有意义的,其中包含工人/人员的 List,并在此列表上提供特定操作。

public String showAllMembers() { ... }
public void notifyAllMembers() { ... }

另外,第二种方式破坏了Single responsibility principle。它不应该关心打印一个人,该类负责添加/删除它们。 Persons 可以为您提供特定的Person,然后您必须在给定实例上调用方法print()

Persons persons = ...;
persons.getMember(10).print(); 

假设我有 10 000 个这样的人。创建 10 000 个类实例有什么缺点吗?

无论如何,您都必须创建 10000 多个实例。考虑一下,

  • 10000Persons + List
  • 10000 Persons + a Persons + a List

【讨论】:

    【解决方案2】:

    第一个比第二个更面向对象,一旦您开始向一个人添加更多属性,这一点就会变得明显。

    例如,考虑为某人添加出生日期。当你拥有class Person 时,你修改了这个类,每个有权访问它的人都可以得到它。您还将使用Person 对象传递出生日期,因此任何将Person 作为参数的方法都可以访问该人的出生日期:

    static void displayPerson(Person p) {
        // Here, we can print both the name and the date of birth / age
    }
    public static void main(String[] args) {
        ...
        displayPerson(people.get(0));
    }
    

    第二种方法需要向Persons 类添加一个并行集合。 Persons 的所有用户都可以访问出生日期,但除非方法将完整集合作为参数,否则它只能访问调用者从集合中获取的属性:

    void displayPerson(String name) {
        // Here, we have no access to person's date of birth
    }
    public static void main(String[] args) {
        ...
        displayPerson(persons.print(0));
    }
    

    【讨论】:

      【解决方案3】:

      在 Java 中,第一种方法是要使用的方法。更符合OOP的做事方式。

      虽然第二个在结构上没有问题,但它不遵循 OOP 架构。您可以在 C 中执行此类操作。

      在第一种方法中,您创建一个 Person 类,它定义了一个人 - 它的属性、方法等。这是面向对象编程中的对象。当您需要 Person 时,您可以实例化一个并将其添加到人员列表中。

      在第二个中,本质上是创建一个数组。然后,您可以创建它的一个实例并填写您想要的属性。但是,我认为这种方法有以下缺点:

      • 您添加到类中的对象不再存在。您在任何地方都没有定义过一个人是什么以及它具有什么属性。这些属性仅存在于您添加到数组的值中。一段时间后,这可能会变得非常混乱和冒险。

      • 没有 getter 和 setter。检索特定属性并对其进行更新的每个操作都会导致对数组进行非常复杂和冗余的迭代。此外,您的类可能具有非常多的属性,并且每次您想要更新属性时,都必须非常小心地在数组中获取该属性的正确索引。这是灾难的根源。

      • 另外,putPerson 方法只是向数组添加一个值?令人毛骨悚然。

      简答:永远不要在 Java 中使用第二种方式。

      【讨论】:

        【解决方案4】:

        在我看来,示例 A 比 B 更容易理解,因此我会说代码可读性和可维护性更好。

        原因是,例如 B,persons 结构实际上涉及组合另一个结构 ArrayList 来完成泛型,在示例 A 中,您可以通过声明 List&lt;Person&gt; 来实现它。

        示例 B 也没有 A 灵活,因为它始终是一个集合,而示例 A 您可以简单地将其用作 Person 并将其插入 Java 中可用的不同数据结构中。例如,如果你想跟踪唯一的人,你可以很容易地得到一个由&lt;name, Person&gt; 键入的地图,而示例 B 不会那么干净,因为你会做类似 &lt;name, Persons&gt; 的事情,其中​​每个 persons将仅包含 1 人。因此,可扩展性可能不如另一个。

        对我来说,A 更像是面向对象的传统方式,因为您将现实世界的对象表示为一个类,而 B 实际上只是一个对象的包装器。

        显然,对此可能有很多争论,但我很高兴看到其他人对此答案的意见和批评。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多