Java 显示用吸气剂
我在研究Java 显示用吸气剂,java,oop,encapsulation,Java,Oop,Encapsulation,我在研究能手/能手,总的想法是他们是邪恶的,应该避免。您应该让对象完成工作,并产生结果 阅读材料: 考虑到所有这些,假设我有一本书class,看起来像这样: publc final Book{ private final String title; private final List<Authors> listofAuthors; private final int numberofpages; //constructor not incl
能手/能手
,总的想法是他们是邪恶的,应该避免。您应该让对象完成工作,并产生结果
阅读材料:
考虑到所有这些,假设我有一本书class
,看起来像这样:
publc final Book{
private final String title;
private final List<Authors> listofAuthors;
private final int numberofpages;
//constructor not included in example.
//getters for title, listofAuthors, and numberofpages
public int numberofpagesleft(int pagesRead){
//code to determine number of pages left
}
public boolean isWrittenBy(Author author){
//code to determine if book contains author
}
}
或
问题:
getTitle()
或getAuthors()
封装
iswritenby()
返回,我将如何显示该书
true
?我该如何收集我图书馆里的所有作者有一个学派声称,大量的get/set方法表明了粗心的面向对象设计。您询问如果
book
对象没有适当的getXXX
方法,您将如何显示“book”数据。答案大概是,你让你的书展示自己:
MyUserInterface interface=...;
...
book.renderToUserInterface (interface);
我认为在使用get/set方法的争论中又有一些力量——我认为一个好的设计会使编程类成为它们所表示的真实世界事物的良好模型,而真实世界的事物通常不仅仅是可以设置和查询的离散数据项的存储库。我认为我们确实有一种倾向,认为类(在Java和其他语言中)只不过是一种修饰的数据结构,而且它们可能不止这些
然而,在我看来,认为get/set方法是“邪恶”的想法太过分了。教条式地避免这些方法不太可能有帮助,特别是当大多数OO程序中发生的许多事情实际上是支持围绕域对象建模的类的基础设施时。此外,“让对象完成工作”在考虑应用程序的完整OO模型时最有意义。在单个对象的设计层面上,例如在通用库中使用,我认为我们必须有点务实
我似乎记得“让对象完成工作”大约在十年前是一个热门的想法,但我不相信这有什么大不了的 对象的属性和对象的实现细节之间存在差异
- 一本书有一个标题——这不是一个实现细节
- 一本书有作者——这不是一个实现细节
- 如何存储一本书的作者——这可能是一个实现细节
class Book {
private ArrayList<Author> authors = new ArrayList<>();
public ArrayList<Author> getAuthors() { return authors; }
}
我们通过包装集合来解决第一个问题:
class Book {
private ArrayList<Author> authors = new ArrayList<>();
public List<Author> getAuthors() {
return Collection.unmodifiableList(authors);
}
}
Book book = ...;
List<Author> authors = book.getAuthors();
我们必须将作者收集到一个新的列表中
,或者更改getAuthors()
的签名,但这会影响那些希望返回列表
的呼叫者
相反,代码应该只返回一个集合
。这不会公开作者
存储的实现细节
class Book {
public Collection<Author> getAuthors() {
return Collection.unmodifiableCollection(authors);
}
}
教材{
公共集合getAuthors(){
返回集合。不可修改集合(作者);
}
}
注意:可能是作者被排序,第一作者被列在第一位。在这种情况下,您可能希望返回一个列表
,向调用者保证数据实际上是有序的。在这种情况下,列表
不是实现细节,而是接口契约的一部分
那么,getTitle()
会破坏封装吗?不,绝对不是
getAuthors()
是否会破坏封装?取决于它的回报和你的承诺。如果它返回一个集合
,则为否。如果它返回一个列表
,并且您没有承诺有序的结果,则为是。这只是对一些不同但相关(有时是高级)主题的辅助注释,并不是对问题的直接回答(在其他答案中已经得到了很好的回答)。可能此处的信息与此处或您的问题无关,如果是,请忽略它:-)
关于不变性,即不添加setter
getter通常很好,因为调用者不能更改对象,但是不必要的setter会使对对象进行推理变得更加困难,尤其是在编写并发代码时
当您使用setter时,对象更改的来源可以来自更广泛的区域、另一个类甚至另一个线程
请参阅Java教程中的和,与一个更复杂、更容易出错的
JavaFX类是JDK中不可变类的一个示例
一般来说,当我创建一个类时,我通常尝试将所有输入放入构造函数参数中,使类成为final,而不是添加setter并使类的所有成员成为final。你不能总是这么做,但当你能做到的时候,对我来说编程似乎更容易了
注意,setter通常是有用的和必需的,所以如果需要,不要担心添加它们,不变性只是一个有时需要的属性,而不是规则
数据模型与显示的桥接
如果您真的对从对象获取数据以进行显示的不同模式和约定感兴趣,那么请阅读Martin Fowler的文章,因为它提供了一个非常好的概述
通常,您希望从data和domain对象以及UI中获得一个新的数据。对于小型应用程序,您不需要这种分离,这只会增加开销。但是,一旦您开始开发更大的应用程序,如果您将UI与域模型完全分离,它通常会变得更有条理。通常,帮助做到这一点,通常与设计模式相结合,如,或
关于JavaFX属性和绑定到显示
如果使用JavaFX,正如您在问题中提到的,请提供一个可观察的干扰
Book book = ...;
ArrayList<Author> authors = book.getAuthors();
class Book {
private ArrayList<Author> authors = new ArrayList<>();
public List<Author> getAuthors() {
return Collection.unmodifiableList(authors);
}
}
Book book = ...;
List<Author> authors = book.getAuthors();
class Book {
private HashSet<Author> authors = new HashSet<>();
public List<Author> getAuthors() {
return Collection.unmodifiableList(authors); // ERROR - authors not a list
}
}
class Book {
public Collection<Author> getAuthors() {
return Collection.unmodifiableCollection(authors);
}
}
@FXML
Label numberOfBooksInLibraryLabel;
Library library = new Library();
...
numberOfBooksInLibraryLabel.textProperty().bind(
library.books().sizeProperty().asString()
);
private final ReadOnlyDoubleWrapper size = new ReadOnlyDoubleWrapper();
public final double getSize() {
return size.get();
}
public final ReadOnlyDoubleProperty sizeProperty() {
return size.getReadOnlyProperty();
}