Printers Instead of Getters

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

获取器和设置器是邪恶的。不需要争论这个问题,这已经决定了。你不同意吗?我们以后再讨论。现在,我们假设我们想要摆脱获取器。关键问题是怎么可能做到呢?我们确实需要从对象中获取数据,对吗?不,错了。

我建议使用“打印机”代替。对象不再通过获取器暴露数据,而是具有将自身“打印”到某种媒体的功能。

假设这是我们的类:

我们需要将其转换为XML格式。一个或多或少传统的方法是通过使用getters和JAXB来实现。

这是一种非常冒犯的对待对象的方式。我们基本上将其内部的一切都公之于众。它是一个小巧的自给自足的实体对象,但我们将其转化为了一袋数据,任何人都可以通过多种方式访问。当然,我们可以访问它以进行阅读。

你可能会说,拥有这些getter方法很方便。我们都习惯于使用它们。如果我们想将其转换为JSON,它们会非常有帮助。如果我们想将这个可怜的对象作为JSP中的数据对象使用,getter方法也会帮助我们。在Java中,有很多例子中都积极地使用getter方法。

这不是因为它们非常有效。而是因为我们的思维方式是如此”过程化”。我们不相信我们的对象。我们只相信它们存储的数据。我们不希望这个Book对象生成XML。我们希望它给我们数据。我们将构建XML。Book太笨了,不能胜任这个工作。我们聪明得多!

我建议停止以这种方式思考。相反,让我们试着给这个可怜的Book一个机会,并为其配备一个”打印机”:

这并不是最好的实现方式,但是你明白了思路。这个对象不再暴露它的内部细节。我们无法获取它的ISBN和标题。我们只能要求它以XML格式打印自身。

如果需要其他格式,我们可以添加一个额外的打印机。

再次强调,这不是最好的实现方式,但你可以看到我想要展示的内容。每次我们需要一个新的格式,我们就创建一个新的打印机。

你可能会说,如果有很多格式的话,对象会变得很大。这是对的,但是一个大的对象本身就是一个不好的设计。我认为,如果有多个打印机,这本身就是一个问题。

那么,如果我们需要多种格式怎么办呢?使用“媒体”,打印机可以打印到这些媒体上。比如,我们有一个代表MySQL中记录的对象。我们希望它可以打印为XML、HTML、JSON以及其他二进制格式等等。我们可以将这么多打印机添加到对象中,但对象会变得庞大而丑陋。为了避免这种情况,引入一个新的对象,代表数据将要打印到的媒体:

再次强调,这是一个非常原始的不可变Media类的设计,但是你已经理解了——media接受数据。现在,我们想要将对象打印为JSON(这个设计并不完美,因为JsonObjectBuilder并不是不可变的,尽管它看起来像一个不可变的对象…)。

现在,我们创建一个JsonMedia的实例,并要求我们的书在那里打印自己。

看啊!JSON对象已经准备好了,书籍并不知道刚刚打印了什么。我们需要将书籍打印成XML吗?我们创建XmlMedia,它将书籍打印成XML格式。Book类保持简洁,而”media”对象的复杂性是无限的。

我在这里的观点很简单——没有getter方法,只有打印器!

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:34

sixnines availability badge   GitHub stars