我正在使用接口依赖注入,但正在考虑如果一个接口发生任何变化,我如何使其可扩展。例如:
function updateStatistics(Interface myInterface)
{
myInterface->prepareStatistics;
myInterface->syncStatistics;
myInterface->doSomething;
myInterface->doSomething2;
...
}
假设只有一个接口需要实现像这样的中间函数
function updateStatistics(Interface myInterface)
{
myInterface->prepareStatistics;
// Do function for only certain implementations
myInterface->syncStatistics;
myInterface->doSomething;
myInterface->doSomething2;
...
}
继续这件事的正确方法是什么?我遇到过很多解决方案
function updateStatistics(Interface myInterface)
{
myInterface->prepareStatistics;
if (myInterface instanceof extensionInterface) {
// Do function for only certain implementations
}
myInterface->syncStatistics;
...
}
updateStatistics
函数分解为它自己的接口方法。但这段代码的主要部分将主要重复,我更喜欢一个事实来源。我想知道正确的 OOP 方法是什么,而不是一个 hacky 解决方案。
假设只有一个接口需要实现像这样的中间函数
为什么会这样呢?接口永远“不需要”来实现任何东西。 接口不实现行为; 类通过实现接口来实现。 这可能会让您觉得语义挑剔,但我强调它是因为这是 OP 中的几个短语之一,这些短语似乎暗示接口是由实现细节驱动的。
但是,如果接口仅反映其实现类的实现细节,那么为什么还要有接口呢?事实上,这意味着当您更改实现时,您可能需要更改接口,从而破坏客户端代码。
相反,
依赖倒置原则抽象不应依赖于细节。细节应该取决于抽象。- Robert C. Martin,
C# 中的敏捷原则、模式和实践不要从实现细节中提取接口定义,而是反转设计的所有权,以便
客户端[...]拥有抽象接口
需要- Robert C. Martin,
C# 中的敏捷原则、模式和实践找出客户端代码
,并围绕这些需求设计界面。
我可以检查注入的接口是否包含额外的接口,然后调用这些函数。这是我最喜欢的解决方案,但它可能会因为 if 语句而使我的函数变得臃肿。重构如果执行运行时类型测试,就破坏了多态性,而这正是接口的全部要点。这可能会导致“霰弹枪手术”,因为您必须在使用相关接口的每个地方重复相同的流量控制结构。
认为这是一种代码味道。 不幸的是,我不能告诉你该怎么做,因为这样一个SOLID练习的重点是从客户端代码需要什么开始,而OP没有描述这一点。