我想知道以下代码是否违反开放封闭原则。
Animal
是Dog
的父类,但是Animal
具有杰克逊注释,可帮助ObjectMapper
(反序列化)这些类。扩展Animal
的任何人都只需要编辑Animal
上存在的注释,以确保(反)序列化能够按预期工作,而不会影响类。
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
// all subclasses
@Type(value = Dog.class, name = "dog")
})
public abstract class Animal {
// fields, constructors, getters and setters
}
public class Dog extends Animal {
}
答案 0 :(得分:2)
确实如此。开闭原理的思想是使对象可扩展,而无需在内部进行修改。由于Animal
的任何新子级都必须对其进行修改才能正常工作,因此这违反了原理。
答案 1 :(得分:0)
Open/closed principle就像整个SOLID是Utopia
。我们应该朝那个方向不断地升级我们的代码,但是可能我们永远都不会结束,因为这是不可能的。让我们阅读下面的文章,看看经典的getters
和annotation
构造如何值得商。
像每个实际的程序员一样,我喜欢使用好的工具来解决问题,而不是自己实现新功能。当要求我将给定模型序列化为JSON
文件时,我正在检查它是否是:
我认为,当我们谈论Jackson
及其注释时,我们可以找到理论与实践之间的黄金中间道路。这要归功于MixIn
功能。您可以将模型与序列化为JSON
的方式分开。当然,当您添加扩展基类的新类时,您需要使用注释更改MixIn
interface
,但这是我们需要付出的代价。
对不起,我忘记回答一个问题,上述示例是否违反了Open/Closed principle
。首先,从Wikipedia
article获取定义:
一个类是封闭的,因为它可以被编译,存储在库中, 基准化,并由客户端类使用。但这也是开放的,因为任何 新类可以将其用作父类,从而增加新功能。当子孙 类已定义,无需更改原始或 打扰客户。
以上示例违反了When a descendant class is defined, there is no need to change the original
部分。即使我们使用MixIn
,也需要更改应用程序的其他部分。更重要的是,如果您的解决方案在99.99%的情况下使用annotations
,则您违反了此部分,因为需要配置某种隐藏在其后面的功能。
答案 2 :(得分:0)
打开/关闭意味着应该打开一个类以进行扩展,但是关闭以进行修改。
换句话说,如果您想更改类的行为,则应该以某种方式扩展它,但不要修改它。
您可以通过
扩展课程TreeSet(Comparator<? super E> comparator)
,因为无需更改TreeSet
本身就可以更改其排序行为。从我的角度来看,@JsonSubTypes
注释不是Animal
类的行为的一部分。它更改了另一个类的行为-对象映射器。因此,这并不是真正的违反。并不是说即使您不更改行为,也必须触摸Animal
类并重新编译它。
这是一个非常奇怪的注释设计。为什么json开发人员不允许您在子类上添加注释,例如就像JPA在层次结构映射中所做的一样。参见DiscriminatorValue
超类型引用子类型是一个奇怪的设计。 抽象类型不应依赖于具体类型。我认为这是应始终适用的原则。