应用 SOLID 原则
Applying SOLID principles
我正在尝试将 SOLID 原则应用于我的项目,但不确定如何处理以下情况:
我有一个界面:
IService
和实现接口
的class
Service : IService
IService
中有许多方法,对于我的项目,我现在需要更新其中一个方法的功能,我们称之为 method1
.
我对 SOLID 的理解是我不应该更新 method1
,而是创建一个扩展 Service
(ServiceV2
) 并覆盖 [=13] 的新 class =]
我的问题是,ServiceV2
应该只扩展Service
,还是需要实现接口IService
,然后扩展Service
并覆盖[=13] =] 只有?
我问的主要原因是因为如果它实现 IService
这会影响我的依赖注入(简单注入器),因为我只能注册一个实现 [=12] 的 class =]
我假设我不会制作一个全新的 IServcieV2
和 ServiceV2
,因为这会失去 IService
和 IServicev2
之间的关系
此外,如果它仅扩展 Service
,我是否仍在实现依赖倒置,因为新的 class 不是直接实现接口,但我想它是间接实现的?
如果 Service
实现 IService
并且 Service2
派生自 Service
,则 Service2
自动实现 IService
,因为 IService
只定义了 签名 的 class 可行 用于特定目的 的一部分。然后使用此 class 或自由签名定义来创建类型,该类型又定义 object
s 成员。
签名不会因继承而改变。它只能得到扩展。
这基本上是您唯一应该使用继承的东西:
如果Service2.Method1()
的可见行为不同于Service.Method1()
的可见行为,这意味着Service2
的可见行为是不同于 Service
的 可见行为 。在这种情况下,您不应使用继承,而应使用实现 IService
的新 class。因为在那种情况下它是一个不同的服务。
让我给你一个具体的例子,虽然是在不同的背景下:
正方形在技术上是矩形的特例,这意味着 Square : Rectangle
。但是,如果正方形的长度发生变化,它的宽度也会发生变化。矩形不是这种情况。因此,如果您有一个包含常规 Rectangle
以及 Square
对象的 List<Rectangle>
,您可以这样做,因为 Square
被定义为 Rectangle
的子对象,你会有 不同的可见行为 。因此,Square
不能是 Rectangle
的子代,因为您不能使用 Rectangle
代替 Square
。所以 Square : Rectangle
是错误的。您可以同时实现将 Length
和 Width
定义为属性的接口 IGeometry
,并在 List<IGeometry>
中同时使用 Rectangles
和 Squares
。接口不指定行为。只是签名。
如果你有一个 IConfigService
你同样会定义 classes FileConfigService
和 DatabaseConfigService
为 FileConfigService : IConfigService
和 DatabaseConfigService : IConfigService
并且有您的 classes 将它们保存为 IConfigService
,因为它们不必关心任何类型的实现细节——它们只需要知道存在几个方法和属性。这也是为什么您为每个 'purpose' 创建一个接口而不是为所有内容创建一个大接口的原因。以及为什么接口只定义 public 成员。
这基本上就是大多数 SOLID 的归结。
如果您只向 IService
实现添加功能,则只更改此 class。没有什么能阻止你。
不过,如果您有类似网络服务之类的东西,并且 运行 系统依赖于它 - 在这种情况下,我会考虑版本控制。
我正在尝试将 SOLID 原则应用于我的项目,但不确定如何处理以下情况:
我有一个界面:
IService
和实现接口
的classService : IService
IService
中有许多方法,对于我的项目,我现在需要更新其中一个方法的功能,我们称之为 method1
.
我对 SOLID 的理解是我不应该更新 method1
,而是创建一个扩展 Service
(ServiceV2
) 并覆盖 [=13] 的新 class =]
我的问题是,ServiceV2
应该只扩展Service
,还是需要实现接口IService
,然后扩展Service
并覆盖[=13] =] 只有?
我问的主要原因是因为如果它实现 IService
这会影响我的依赖注入(简单注入器),因为我只能注册一个实现 [=12] 的 class =]
我假设我不会制作一个全新的 IServcieV2
和 ServiceV2
,因为这会失去 IService
和 IServicev2
此外,如果它仅扩展 Service
,我是否仍在实现依赖倒置,因为新的 class 不是直接实现接口,但我想它是间接实现的?
如果 Service
实现 IService
并且 Service2
派生自 Service
,则 Service2
自动实现 IService
,因为 IService
只定义了 签名 的 class 可行 用于特定目的 的一部分。然后使用此 class 或自由签名定义来创建类型,该类型又定义 object
s 成员。
签名不会因继承而改变。它只能得到扩展。 这基本上是您唯一应该使用继承的东西:
如果Service2.Method1()
的可见行为不同于Service.Method1()
的可见行为,这意味着Service2
的可见行为是不同于 Service
的 可见行为 。在这种情况下,您不应使用继承,而应使用实现 IService
的新 class。因为在那种情况下它是一个不同的服务。
让我给你一个具体的例子,虽然是在不同的背景下:
正方形在技术上是矩形的特例,这意味着 Square : Rectangle
。但是,如果正方形的长度发生变化,它的宽度也会发生变化。矩形不是这种情况。因此,如果您有一个包含常规 Rectangle
以及 Square
对象的 List<Rectangle>
,您可以这样做,因为 Square
被定义为 Rectangle
的子对象,你会有 不同的可见行为 。因此,Square
不能是 Rectangle
的子代,因为您不能使用 Rectangle
代替 Square
。所以 Square : Rectangle
是错误的。您可以同时实现将 Length
和 Width
定义为属性的接口 IGeometry
,并在 List<IGeometry>
中同时使用 Rectangles
和 Squares
。接口不指定行为。只是签名。
如果你有一个 IConfigService
你同样会定义 classes FileConfigService
和 DatabaseConfigService
为 FileConfigService : IConfigService
和 DatabaseConfigService : IConfigService
并且有您的 classes 将它们保存为 IConfigService
,因为它们不必关心任何类型的实现细节——它们只需要知道存在几个方法和属性。这也是为什么您为每个 'purpose' 创建一个接口而不是为所有内容创建一个大接口的原因。以及为什么接口只定义 public 成员。
这基本上就是大多数 SOLID 的归结。
如果您只向 IService
实现添加功能,则只更改此 class。没有什么能阻止你。
不过,如果您有类似网络服务之类的东西,并且 运行 系统依赖于它 - 在这种情况下,我会考虑版本控制。