我在SESE上读到了这个关于封装和getters/ssetter的答案。假设我喜欢使用不可变类,所以如果实现了setter,它将返回一个反映更改的新对象,例如:
//return a new Book reflecting the price change.
public Book updatePrice(double price){}
在链接中,答案建议我有一个名为getDisplayinformation()
的方法,它返回一个数据结构。
(想想由枚举、结构或无方法类索引的数组)
根据此建议,我将如何返回带有作者列表的书籍?
public final class Author{
private final String id;
private final String firstname;
private final String lastname;
//Constructor
}
public final class Book{
private String bookID;
private final String title;
private List<Author> authorsList;
private double price;
//Constructor
}
假设我想返回一个Map<String,String>
。
public Map<String,String> getDisplayinformation(){
Map<String,String> displayMap = new HashMap<String,String>();
display.put("BookTitle", title);
display.put("ID", bookID);
display.put("Price", price.toString())
//insert authorsList;
return displayMap;
}
你引用的答案有一半是对的。为字段提供getter会破坏封装,因为这会使调用者依赖于某些内部结构。
现在,返回一个调用方需要知道密钥并知道信息是什么的映射,基本上与为该字段提供getter没有什么不同。
面向对象试图告诉我们,功能需要与数据捆绑在一起。因此,Book
必须有一些方法来呈现Book
。我不会称之为getDisplayInformation()
,而更简单地说是display()
。它可以返回一些东西,也可以获取相关参数。
关键是,display()
返回的任何内容都必须与演示有关,而不能与书籍有关。关于作为一本书的语义应该在这一点上丢失,否则调用者将紧密耦合。
所以,可以返回一个XML文档、JSON文档、HTML、WicketComponent
,无论它是什么,都可以用于独立于Book
的表示。
或者,该方法可以采用一个参数将其自身呈现给。比如AWTComponent.paint(Graphics g)
之类的。
注:这实际上是一个有争议的话题。混合范式开发(过程和ood的混合)认为表示需要与对象分离,而面向对象则认为数据和功能总是属于一起的。