【问题标题】:Encapsulation and Getters封装和吸气剂
【发布时间】:2017-09-28 05:12:40
【问题描述】:

我正在阅读这篇article 为何gettersetters 是邪恶的。文章并没有说不要永远使用它们,而是告诉你以一种限制使用这些方法的方式思考,或者引用文章:

不要要求你提供工作所需的信息;问对象 具有为您完成工作的信息。

当您需要在 GUI 中显示数据但没有 getter 方法时会发生什么?本文简要介绍了这一点,但并不完整。它提到将 JComponent 传递给类,但如果您是 GUI 更改,它可能会导致大量工作需要修复。

例如,您有一个 Book 类(限制此示例以保持其可读性)。

public final class Book {

    private String title;
    //Authors is class with the attributes authorFirstname, authorLastname
    private List<Author> listofAuthors;


    public Book(String title, List<Author> listofAuthors)
    {
        //initialization
    }

    //other methods that do work
}

如果我有一个 GUI,其中有一个 JTextField 来显示书名和一个 JTable 来显示作者列表,我将如何编写我的方法来为我“完成工作”并显示结果?这是需要getter 的时候吗?

【问题讨论】:

标签: java oop methods encapsulation getter


【解决方案1】:

Allen Holub 的文章(您提到的那篇)是完全正确的,您不应该要求提供数据,至少在您进行面向对象时是这样。不,展示东西不是打开对象的正当借口。

如果您有Book,只需请求Book 显示即可!使用JTextFieldJTable 或其他什么都无关紧要。当然,根据您的要求,您可以这样做:

public final class Book {
    ...
    JComponent display() {
        ...
    }
}

当然,面向对象的重点在于,您正在尝试本地化更改(尽可能限制为一个类)。做到这一点的唯一方法是将依赖于相同事物的功能本地化到(最好)相同的类中。也称为增加“凝聚力”。

所以现在,如果Book 内部发生变化,所有的事情,包括Book 的显示方式都在Book 本身中,所以没有必要“寻找”使用@ 的代码987654330@.

现在,对于这不是“干净”的答案,因为您将演示代码与“业务逻辑”混合在一起。值得注意的是,不将表示与“业务逻辑”混合的整个想法来自早期,当时我们仍然认为表示可能对“业务对象”是“远程”的,而“业务对象”可能是被多个应用程序用于不同的事情。 IE。多层设计。 YAGNI。大多数时候,没有真正的理由在单个应用程序中设置人为的技术边界。如果Book 知道它是 GUI 应用程序的一部分,并且有真正的好处(可维护性),则不会造成任何伤害。

编辑:这是 `display() 方法的详细外观,显示标题和作者(Swing 的伪代码):

public final class Book {
    private final String title;
    private final List<Author> authors;
    ...
    public JComponent display() {
        JPanel bookPanel = new JPanel();
        bookPanel.add(new JLabel(title));
        JList authorsList = new JList(); // Or similar
        for (Author author: authors) {
            authorsList.add(author.display());
        }
        bookPanel.add(authorsList);
        return bookPanel;
    }
}

然后,您可以简单地 add() 将该组件添加到您想要在其中显示图书的任何摆动容器中。

【讨论】:

  • 假设我有一个 JTable 来显示作者,只是为了学习目的,你能否通过展示如果没有 getter 时如何显示作者列表来完成代码?
  • 您不应该“拥有”JTable 来显示作者。您应该要求本书为您显示其作者。例如:JComponent displayAuthors()
  • 裸露在外,我不完全明白。我将如何要求它为我显示作者?这就是为什么我问你是否可以完成你的示例代码。
  • 查看编辑。我假设Author 对象也知道如何显示自己。
  • 太棒了。非常感谢您的示例和解释。通过这个例子,我可以自己找出 Author 对象。
【解决方案2】:

您可以创建三种类:

  1. 实体,代表业务概念且只有一个唯一 ID 的类,例如 ID 为用户名的客户端类。它通常是一个可变类。您应该在这里拥有所有业务逻辑。你不应该用 getter 和 setter 打开他的数据。

  2. Value 对象,代表业务概念但没有唯一 ID 的类,如 Email 类。它通常是一个 imm.utable 类。您应该在这里拥有所有业务逻辑。

  3. 数据结构(一种 DTO),只保存数据的类,没有行为,也许你有 setter 和 getter 来访问这些数据。

如果我没有访问器,我需要访问所有客户端数据,我该怎么办?好吧,您应该将 Client 转换为 DTO。您可以使用像 Orika 这样的框架。或者您可以在 Client 类中创建一个方法来询问信息(中介模式)。

我喜欢第二种选择,但它意味着更多的工作:

class Client{
    private String name;
    ...
   public void publishInfo(ClientInfo c){
      c.setName(name);
      ...
    }
}

class ClientInfo{
    private String name;
    //GETTERS
    //SETTERS
}

【讨论】:

    【解决方案3】:

    这样想:Getter(公共函数)是私有属性的桥梁。

    我会写一个简单的例子来使用 OOP 修改你的 TextField。

    书籍类:

    public final class Book {
    private String title;
    //Authors is class with the attributes authorFirstname, authorLastname
    private List<Author> listofAuthors;
    
    
    public Book(String title, List<Author> listofAuthors)
    {
        //initialization
    }
    public String getTitle() {
    return this.title; }
    }
    

    图形界面:

    author1 = new Author("jhon");
    author 2 = new Author("alsojhon");
    list = new ArrayList();
    list.add(author1);
    list.add(author2)
    b = new Book("stack",list);
    JTextField field;
    field.setText(b.getTitle());
    

    【讨论】:

      【解决方案4】:

      您是在询问一种为您显示所有信息的方法吗?我没有关注。

      如果这是您的要求,我的建议是:不要在包含窗口代码的类中编写它。不会很干净。使用该方法创建一个新类(是的,getter 是必要的,它们使 OOP 更容易,但这是有偏见的)。

      如果我想遍历一个列表,我要做的是创建一个 StringBuilder,以及一个添加作者姓名的 for 循环。然后,让该方法返回作者列表。

      List<Authors> a;
      StringBuilder d = new StringBuilder();
      for (int i = 0; i < a.size(); i++) {
          d.append(a.get(i).getName() + ", ");
      }
      return d.toString();
      //It's just sudo code, but still.
      

      【讨论】:

      • 我正在努力完成文章所说的事情,让班级为您完成工作。它说虽然你可以使用 getter,但最好避免使用它们。
      • Getter 和 Setter 使对象的结构更加整洁。但我想每个人都有自己的编程风格。
      猜你喜欢
      • 1970-01-01
      • 2019-11-26
      • 2018-11-16
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多