提醒(从
wiki):
The interface-segregation principle (ISP) states that no client should
be forced to depend on methods it does not use.
现在看看我的例子.
这是我可变的实体.它是从某个地方编辑的,它能够通过只读接口通知有关更改:
interface ICounter
{
event Action<int> NewNumber;
}
class Counter : ICounter
{
public event Action<int> NewNumber;
int number = 0;
public void IncrementAndSend(int x)
{
number += x;
if (NewNumber != null) NewNumber(number);
}
}
这是使用它的传输层的类.看看两种注射变体(Attach_1和Attach_2)以及我的假设如下:
class OneToManyRouter
{
IEnumerable<Counter> _destinations;
public OneToManyRouter(IEnumerable<Counter> destinations)
{
_destinations = destinations;
}
// 1
public void Attach_1(ICounter source)
{
source.NewNumber += (n) =>
{
foreach (var dest in _destinations) dest.IncrementAndSend(n);
};
}
// 2
public void Attach_2(Counter source)
{
source.NewNumber += (n) =>
{
foreach (var dest in _destinations) dest.IncrementAndSend(n);
};
}
}
> ISP是关于真实物体的.你不能使用“过度”
对传入参数的引用.
> ISP是关于课程的.如果您的班级已使用完整界面
某处,不需要在特定方法中限制引用类型.
在这个例子中,ICounter接口过多.
>从SOLID的角度来看,这种架构是完全错误的
原则(那么为什么?).
最佳答案 ISP既不是类,也不是对象,而是严格关于接口,特别是关于接口设计.该原则旨在阻止在单个接口中对半相关方法进行分组,以避免用户只需要这些方法的子集将其余部分实现为空函数(抛出NotImplementedException或将其保留为字空:{}) .因此,更容易实现更一致的类并更有效地使用接口.
在您的示例中,您将Counter类与ICounter接口组合在一起,其方式与ISP概念没有直接关系:
- ISP is about real objects. You must not use “excessive” references to incoming parameters.
这部分是正确的(如果我正确地解释“过度”的概念).但是,正如我所提到的,ISP并不是关于如何与真实对象进行交互,而是如何定义有用的界面.
- ISP is about classes. If your class already uses full interface somewhere, no need to restrict reference type in particular methods. ICounter interface is excessive in this example.
这是不正确的.如果您在具体类而不是在接口上创建依赖项,则该类实现接口的事实并不意味着什么.请记住,通过使组件依赖于合同而不是将来可能会更改的特定实现,接口提供了程序各个部分的分离.通过使用具体课程,您将失去这种好处.而且,这与ISP概念并不完全相关.
- This architecture is completely wrong from the point of SOLID principles (then why?).
从体系结构的角度强调SOLID原则,我建议依赖于ICounter而不是Counter,并将IncrementAndSend作为接口定义的一部分.