封装和吸气剂
Encapsulation and Getters
我正在读这个 article 关于为什么 getter
和 setters
是邪恶的。这篇文章并没有说不要永远使用它们,但是,它告诉你以一种限制使用这些方法的方式思考,或者引用这篇文章:
Don't ask for the information you need to do the work; ask the object
that has the information to do the work for you.
当您需要在 GUI 中显示数据但没有 getter 方法时会发生什么?这篇文章简要介绍了这一点,但并不全面。它提到将 JComponent 传递给 class,但如果您更改了 GUI,则可能需要进行大量修复工作。
例如,您有一本书 class(限制此示例以保持其可读性)。
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
来显示作者列表,我该如何将我的方法写到 "do the work"我并显示结果?这是一个需要 getter
的时代吗?
你问的是一种为你显示所有信息的方法吗?我不关注了。
如果这就是您要问的,我的建议是:不要将它写在 class 中,其中包含 window 代码。不会很干净。使用该方法创建一个新的 class(是的,吸气剂是必需的,它们使 OOP 更容易,但这是有偏见的)。
如果我想循环访问一个列表,我会做一个 StringBuilder 和一个 for 循环,它会添加作者的名字。然后,使用方法 return 作者列表。
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(public 函数)是私有属性的桥梁。
我会给你写一个简单的例子来使用 OOP 修改你的 TextField。
图书class:
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());
您可以创建三种 classes:
实体,class表示一种业务概念并且只有一个唯一 ID,如 Client class,Id 为用户名。它通常是一个可变的class。您应该在此处拥有所有业务逻辑。你不应该用getters和setters打开他的数据。
值对象,class表示业务概念但没有唯一 ID 的元素,例如电子邮件 class。它通常是 imm.utable class。您应该在此处拥有所有业务逻辑。
数据结构(DTO 的一种),classes 只保存数据,没有行为,也许你有 setter 和 getter 来访问这些数据。
如果我没有访问器,需要访问所有客户端数据怎么办?那么,您应该将 Client 转换为 DTO。您可以使用像 Orika 这样的框架。或者您可以在客户端 class 中创建一个方法来请求信息(中介模式)。
我喜欢第二个选项,但它意味着更多的工作:
class Client{
private String name;
...
public void publishInfo(ClientInfo c){
c.setName(name);
...
}
}
class ClientInfo{
private String name;
//GETTERS
//SETTERS
}
Allen Holub 的文章(您提到的那篇)是完全正确的,您不应该索取数据,至少在您做 Object-Orientation 的时候。不,展示东西不是打开 object.
的有效借口
如果您有 Book
,只需要求 Book
显示它自己!使用 JTextField
或 JTable
或其他什么都不重要。当然,根据您的要求,您可以这样做:
public final class Book {
...
JComponent display() {
...
}
}
Object-Orientation 的重点当然是您正在尝试本地化更改(尽可能限制为一个 class)。做到这一点的唯一方法是将依赖于相同事物的功能本地化为(最好)相同的 class。也称为递增 "cohesion".
所以现在,如果 Book
内部发生变化,所有的东西,包括 Book
的显示方式都在 Book
本身,所以没有必要 "hunt" 用于使用 Book
.
的代码
现在,对于这不是 "clean" 的答案,因为您将表示代码与 "business logic" 混合在一起。值得注意的是,不将 presentation 与 "business logic" 混合的整个想法来自早期,当时我们仍然认为 presentation 可能是 "remote" 到 "business objects",其中 "business objects" 可能被多个应用程序用于不同的事情。 IE。 multi-tier 设计。 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()
将该组件添加到您想要在其中显示书籍的任何 swing 容器。
我正在读这个 article 关于为什么 getter
和 setters
是邪恶的。这篇文章并没有说不要永远使用它们,但是,它告诉你以一种限制使用这些方法的方式思考,或者引用这篇文章:
Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.
当您需要在 GUI 中显示数据但没有 getter 方法时会发生什么?这篇文章简要介绍了这一点,但并不全面。它提到将 JComponent 传递给 class,但如果您更改了 GUI,则可能需要进行大量修复工作。
例如,您有一本书 class(限制此示例以保持其可读性)。
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
来显示作者列表,我该如何将我的方法写到 "do the work"我并显示结果?这是一个需要 getter
的时代吗?
你问的是一种为你显示所有信息的方法吗?我不关注了。
如果这就是您要问的,我的建议是:不要将它写在 class 中,其中包含 window 代码。不会很干净。使用该方法创建一个新的 class(是的,吸气剂是必需的,它们使 OOP 更容易,但这是有偏见的)。
如果我想循环访问一个列表,我会做一个 StringBuilder 和一个 for 循环,它会添加作者的名字。然后,使用方法 return 作者列表。
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(public 函数)是私有属性的桥梁。
我会给你写一个简单的例子来使用 OOP 修改你的 TextField。
图书class:
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());
您可以创建三种 classes:
实体,class表示一种业务概念并且只有一个唯一 ID,如 Client class,Id 为用户名。它通常是一个可变的class。您应该在此处拥有所有业务逻辑。你不应该用getters和setters打开他的数据。
值对象,class表示业务概念但没有唯一 ID 的元素,例如电子邮件 class。它通常是 imm.utable class。您应该在此处拥有所有业务逻辑。
数据结构(DTO 的一种),classes 只保存数据,没有行为,也许你有 setter 和 getter 来访问这些数据。
如果我没有访问器,需要访问所有客户端数据怎么办?那么,您应该将 Client 转换为 DTO。您可以使用像 Orika 这样的框架。或者您可以在客户端 class 中创建一个方法来请求信息(中介模式)。
我喜欢第二个选项,但它意味着更多的工作:
class Client{
private String name;
...
public void publishInfo(ClientInfo c){
c.setName(name);
...
}
}
class ClientInfo{
private String name;
//GETTERS
//SETTERS
}
Allen Holub 的文章(您提到的那篇)是完全正确的,您不应该索取数据,至少在您做 Object-Orientation 的时候。不,展示东西不是打开 object.
的有效借口如果您有 Book
,只需要求 Book
显示它自己!使用 JTextField
或 JTable
或其他什么都不重要。当然,根据您的要求,您可以这样做:
public final class Book {
...
JComponent display() {
...
}
}
Object-Orientation 的重点当然是您正在尝试本地化更改(尽可能限制为一个 class)。做到这一点的唯一方法是将依赖于相同事物的功能本地化为(最好)相同的 class。也称为递增 "cohesion".
所以现在,如果 Book
内部发生变化,所有的东西,包括 Book
的显示方式都在 Book
本身,所以没有必要 "hunt" 用于使用 Book
.
现在,对于这不是 "clean" 的答案,因为您将表示代码与 "business logic" 混合在一起。值得注意的是,不将 presentation 与 "business logic" 混合的整个想法来自早期,当时我们仍然认为 presentation 可能是 "remote" 到 "business objects",其中 "business objects" 可能被多个应用程序用于不同的事情。 IE。 multi-tier 设计。 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()
将该组件添加到您想要在其中显示书籍的任何 swing 容器。