实现.NET Framework接口的接口隔离原则

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现.NET Framework接口的接口隔离原则相关的知识,希望对你有一定的参考价值。

我正在将IServiceLocator(CommonServiceLocator包)实现到我的自定义ServiceLocator类中。

该接口具有以下实现方法:

public class CustomServiceLocator : IServiceLocator

    private IServiceProvider _provider;

    public RatioDissectionServiceLocator(IServiceProvider provider)
    
        _provider = provider;
    

    public IEnumerable<object> GetAllInstances(Type serviceType)
    
        throw new NotImplementedException();
    

    public IEnumerable<TService> GetAllInstances<TService>()
    
        throw new NotImplementedException();
    

    public object GetInstance(Type serviceType)
    
        throw new NotImplementedException();
    

    public object GetInstance(Type serviceType, string key)
    
        throw new NotImplementedException();
    

    public TService GetInstance<TService>()
    
        return _provider.GetService<TService>();
    
 

我不想在我的班级中实现所有方法。我们如何为内置的C#接口实现ISP?

有帮助吗?

答案

接口隔离原则指出:

不应该强迫任何客户端依赖它不使用的方法。

这意味着尽管对该原则有许多不清楚和误导性的解释,但一个大的界面本身并不违反这一原则。也许另一个类实际上确实依赖于接口的所有成员。因此,我们不会看到像IServiceLocator这样的界面,并尝试以某种方式“修复”它。

ISP是从依赖于接口的类的角度出发的。如果一个接口有20个成员而我的类依赖于所有这些成员,那么它不是ISP违规。 (这可能是与ISP无关的各种其他坏事。)如果另一个类依赖于完全相同的接口并且仅使用少数成员,那就是ISP违规。

在两个示例中,它都是相同的界面。原则不是关于界面。它取决于依赖于接口的类是否使用其所有成员。

(另一个奇怪的例子我看到很多是一个大的接口和一个实现接口的类但是为某些成员抛出NotImplementedException。这也很糟糕,这是Liskov Substitution违规,但它与ISP没有任何关系。实现一个界面不依赖于它。)

避免ISP违规的一种方法是从依赖于它们的类的角度编写接口。无论您的类需要依赖它,请编写您的界面以准确描述它。如果具体的内部实现是一个包含100个成员的框架类,请将其包装在您自己的类中:

public interface ISmallSegregatedInterface

    void DoJustWhatMyClassNeeds();


public class TheImplementation : ISmallSegregatedInterface

    private readonly FrameworkClassWithLotsOfMembers _inner;

    public TheImplementation(FrameworkClassWithLotsOfMembers inner)
    
        _inner = inner;
    

    public void DoJustWhatMyClassNeeds()
    
        _inner.CallSomeMethod();
    

现在,需要依赖于一个方法的类可以依赖于只有一个方法的接口。 (随着时间的推移,我发现这导致了许多单方法接口。我认为逻辑上导致depending on functions and delegates,但单方法接口是可以的。

这就是界面隔离。您的课程不依赖于他们不需要的大型界面。它们依赖于一个或多个接口来准确描述它们的需求。这通常是通过从需要依赖它的类的角度创建接口来实现的。


您可能会发现,没有类需要依赖IServiceLocator的所有方法。

也许你需要的只是这个:

TService GetInstance<TService>();

但是一个类真的需要依赖一个可以返回任何东西的方法吗?换句话说,您可能只会请求一个或两个依赖项。所以也许你真正需要的是这个:

public interface ISomethingSpecificFactory

    ISomethingSpecific CreateInstance();

或者您可能会发现您根本不需要工厂 - 也许您可以注入ISomethingSpecific而不是创建ISomethingSpecific实例的工厂。

另一种看待它的方法:如果你不需要实现IServiceLocator的所有方法,那么你不需要创建一个实现IServiceLocator的类。


IServiceLocator是一个框架接口。与我们创建的大多数软件不同,它不存在以满足狭窄的特定需求。它满足了我们编写软件时确定的更广泛的需求。这就是为什么它有更多的意义,它有各种各样的方法,我们可能不需要。

ISP的一个原因是,如果许多类依赖于接口的不同成员,我们可能会因为一个客户端的需要而被迫改变接口,并且这些更改会影响依赖于其他方法的其他客户端,实际上是耦合他们都在一起。

我们不能改变IServiceLocator以便不存在压力。从技术上讲,即使我们依靠该接口确实违反了ISP,也不会产生ISP保护我们的有害影响。

以上是关于实现.NET Framework接口的接口隔离原则的主要内容,如果未能解决你的问题,请参考以下文章

C#中啥叫接口隔离原则?

面向对象设计原则七:接口隔离原则

单一职责原则和接口隔离原则区别的理解

迪米特原则与接口隔离原则

6大设计原则之接口隔离原则

面向对象编程原则(07)——接口隔离原则