忘记你在 OOP 学校学到的东西吧!
三年来我们取得了长足的进步。我们现在有更好的语言。 Swift、Rust、Kotlin、Go 等。我们了解数据/值类型和操作它的代码之间的区别。正确的企业 CLEAN 架构在 Java 领域提倡这一点。但 Java 并不为此类模式提供语言级支持。最终结果是大量使用(仍然很棒)诸如 RxJava 之类的东西,以及进行代码生成的注释处理器等。但是现在很难高兴地拖着 Java 的遗产。 Kotlin 倾向于以 Java 无法解决的方式解决 Java 的问题very最低代价:失去严格的源兼容性(不是 Groovy)。
原始答案,底部有更新。
有两个答案。
One:
无用的样板!
如果类代表一些大数据对象,那么听起来大多数成员变量只是数据的容器。当出现这种情况时,严格遵循信息隐藏的 OOP 约定就不再那么重要了。人们经常混淆这个约定的目的并最终滥用它。它只是为了防止程序员必须处理对象复杂且不必要的内部工作。不要遮盖整个对象,而只需遮盖不应该被弄乱的部分。如果您只是从数据库映射信息或充当存储容器,则代码如下:
import java.util.Date;
public class Article {
protected int id;
protected String guid;
protected String title;
protected String link;
protected Date pubDate;
protected String category;
protected String description;
protected String body;
protected String comments;
protected Article (String articleTitle, String articleBody) {
title = articleTitle;
body = articleBody;
}
protected Article (String guid, String articleTitle, String articleLink,
long publicationDate, String category, String description,
String articleBody, String commentsLink) {
this(articleTitle, articleBody);
this.guid = guid;
this.link = articleLink;
this.pubDate = new Date(publicationDate);
this.category = category;
this.description = description;
this.comments = commentsLink;
}
protected Article (int id, String guid, String articleTitle, String articleLink,
long publicationDate, String category, String description,
String articleBody, String commentsLink) {
this(guid, articleTitle, articleLink, publicationDate,
category, description, articleBody, commentsLink);
this.id = id;
}
protected int getId() {
return id;
}
protected String getTitle() {
return title;
}
protected String getGuid() {
return guid;
}
protected String getLink() {
return link;
}
protected String getComments() {
return comments;
}
protected String getCategory() {
return category;
}
protected String getDescription() {
return description;
}
protected String getBody() {
return body;
}
protected void setId(int id) {
this.id = id;
}
protected void setGuid(String guid) {
this.guid = guid;
}
protected void setTitle(String title) {
this.title = title;
}
protected void setLink(String link) {
this.link = link;
}
protected void setPubDate(Date pubDate) {
this.pubDate = pubDate;
}
protected void setCategory(String category) {
this.category = category;
}
protected void setDescription(String description) {
this.description = description;
}
protected void setBody(String body) {
this.body = body;
}
protected void setComments(String comments) {
this.comments = comments;
}
}
..实在是太可恶了。
在这种情况下,实际上没有理由仅仅为了访问数据对象的成员而完成所有额外的工作。特别是如果您只是在几行外部代码中使用它们:
public OtherClass {
private Article article;
public OtherClass(Article data) {
article = data;
}
public String getArticleContents() {
return (new StringBuilder())
.append(article.getTitle())
.append(article.getCategory())
.append(dateToString(article.getPubDate())
.append(article.getBody())
.toString();
}
}
只需直接访问成员即可节省数百行代码(就像您建议您尝试做的那样)。
这引出了这个问题的第二个答案。
Two:
设计臭..
您的代码可能正在腐烂。厨师拉姆齐会感到羞愧。原因如下:
上面说的很清楚OtherClass
完全没用,因为它的功能可以(并且应该)放在Article
类而不是包含在其他一些无用的、不需要的、文件系统垃圾中OtherClass
。如果你这样做,你甚至可以忘记需要 getter 和 setterand OtherClass
因为与之交互的东西可能只需要文章内容而不是单独的标题、正文等。在这种方法中Article
class 对外界隐藏了所有内容,只提供绝对需要的信息。
由于这是您问题的两个完全可行的答案,因此必须有一个解决方案j
on.
使用 Clojure
对象建模
虽然你可以使用闭包来建模对象 http://pramode.net/clojure/2010/05/26/creating-objects-in-clojure/,还有更好的方法。有趣的是,在一种将函数视为一等公民的语言中,您可以完全使用映射来建模传统的面向对象范例 - 正如您在重构 30 多个成员字段类系统时开始发现的那样被给予。
将此与原件进行比较Article
+ OtherClass
方法:
(defn Article []
(let [id (atom nil)
guid (atom nil)
title (atom nil)
link (atom nil)
pubdate (atom nil)
category (atom nil)
description (atom nil)
body (atom nil)
comments (atom nil)
set (fn [g t l p cg d b cm]
(do (reset! guid g)
(reset! title t)
(reset! link l)
(reset! pubdate p)
(reset! category cg)
(reset! description d)
(reset! body b)
(reset! commments cm)))
get (fn [] [@guid
@link
@description
@comments
:content (content)])
content #(str title category pubdate body)]
{:get get, :set set}))
上面的例子是一个系统,它从两个答案中获取要点,并将它们组合成一个隐藏不需要的成员的系统,合并逻辑功能(获取“内容”的功能),并使用一种不需要大量闪亮样板的语言代码..
替换类/对象系统
虽然这是如何使用函数式语言对对象进行建模的一个很好的示例,但它对于 Clojure 和一般函数式编程来说并不完全惯用。要获得处理结构化数据的更简单方法,请查看 Clojure结构图 http://clojure.org/data_structures#Data%20Structures-StructMaps and Records http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defrecord.
2017年更新
只需使用Kotlin https://kotlinlang.org/。它正在全面治愈爪哇病。它对所有这些事情都有一流的语言支持,编译器甚至可以帮助您摆脱无用的样板文件。它已经存在了 7 年多了,自 2016 年 2 月起就发布了稳定版本。如果我一开始就知道它,我可能不会包含 Closure。