在我的应用程序中,我有 N 个子类,它们都扩展了一个超类。每个类都有自己的
serialize
实现,但它们共享一些通用代码。例如:
class Serializer {
serialize = () => throw Exception("...")
}
class JSONSerializer extends Serializer {
serialize = () => {
console.log("Formatting...")
// ...
}
}
class XMLSerializer extends Serializer {
serialize = () => {
console.log("Formatting...")
// ...
}
}
如果我将公共代码在超类中包装在函数
format
中并在子类中调用它,我是否违反了SOLID原则(特别是接口继承优于实现继承-Liskov替换-)?如果是,我该如何坚持原则?
class Serializer {
format = () => console.log("Formatting...")
serialize = () => throw Exception("...")
}
class JSONSerializer extends Serializer {
serialize = () => {
this.format()
// ...
}
}
class XMLSerializer extends Serializer {
serialize = () => {
this.format()
// ...
}
}
您对代码的修改不违反 SOLID 原则。将公共代码提取到超类中并在子类中调用它们符合这些原则。
原因如下:
单一职责原则(SRP):每个类都有一个单一的职责 责任。序列化器负责格式化,并且 JSONSerializer 和 XMLSerializer 负责创建它们的 特定类型的序列化。
开闭原则(OCP):Serializer类是开放的 扩展但关闭修改。您可以添加新的类 继承自 Serializer,但您没有修改 Serializer 类 每次您需要新型序列化器时。
里氏替换原则(LSP):子类可以用于 父类的位置而不会引起问题。你没有违反 这是因为子类中的序列化函数没有执行 任何会破坏函数定义的东西 序列化器类。
接口隔离原则 (ISP):不应强迫客户端 取决于他们不使用的接口。我们没有看到任何界面 这里有依赖关系,所以不违反这个原则。
依赖倒置原则(DIP):高层模块不应该 依赖于低级模块。两者都应该依赖于抽象。这 Serializer 中的高级序列化方法不依赖于 低级格式化方法的详细信息。
此外,很好地应用了Dry(Don’t Repeat Yourself)原则,将通用的代码格式移至父类Serializer中,从而增强了代码的可维护性,减少了潜在的错误。
请注意,直接从超类抛出异常可能不是理想的做法,相反,您可以将其构造为返回未实现的消息或以其他方式处理它。