oop - 接口(interface)实现(接口(interface)隔离原则)

标签 oop interface interface-segregation-principle

我遇到了一种情况,我需要调用第三方服务来获取一些信息。这些服务对于不同的客户可能会有所不同。我的界面中有一个身份验证功能,如下所示。

interface IServiceProvider {

bool Authenticate(string username, string password);
}

class ABCServiceProvider : IserviceProvider 
{
 bool Authenticate(string username, string password) { // implementation}
}

class EFGServiceProvider : IserviceProvider 
{
 bool Authenticate(string username, string password) { // implementation}
}

等等...现在我遇到了一个服务提供商(比如说 XYZServiceProvider),它需要一些附加信息(agentid)进行身份验证。像这样的东西...

class XYZServiceProvider
{
 bool Authenticate(string username, string password, int agentid) { // implementation}
}

现在,如果我在接口(interface)中提供另一个具有 3 个参数的 Authenticate 函数,并在除 XYZServiceProvider 之外的所有类中抛出未实现的异常,是否会违反接口(interface)隔离原则?我在代码的其他部分也有类似的情况。谁能告诉我实现这种场景的最佳方法是什么?我真的会非常感激。

最佳答案

解决这个问题的最好方法可能是在接口(interface)中要求 agentId,并且在 ABC 和 DEF 不需要它的情况下简单地忽略它。这样,消费阶层仍然不会知道其中的区别。

实际上,如果要互换使用 ABC、DEF 和 XYZ 提供程序,则最重要的是里氏替换原则; “给定类 X 依赖的类 A,X 应该能够使用从 A 派生的类 B,而不知道其中的区别”。

接口(interface)隔离原则基本上说接口(interface)不应包含其任何使用者不需要的成员,因为如果这些成员的定义发生更改,甚至不使用该方法的类都必须重新编译因为他们所依赖的接口(interface)已经改变了。虽然这是相关的(如果添加重载,则必须重新编译 IServiceProvider 的所有使用者),但如果更改 Authenticate() 的签名,则无论如何都必须这样做,并且从维护的角度来看更紧迫的问题是,如果您添加了 Authenticate() 的重载,您的消费者现在必须知道他们需要使用哪个重载。这要求您的消费类了解公共(public)接口(interface)实现之间的差异,从而违反了 LSP。提供比特定提供者需要的更多信息从来都不是问题,但是在仅提供两个输入的用法中使用 XYZ 就会出现问题。为了避免这些问题,您总是会使用三参数重载,那么为什么要使用两参数重载呢?

现在,如果 IServiceProvider 当前的使用是在没有也不关心 agentId 的区域,因此很难开始提供它,那么我会推荐一个具体 XYZ 提供程序插入的适配器,它实现您当前的 IServiceProvider,并通过其他方式提供 agentId 使新提供程序像旧提供程序一样工作:

public class XYZAdapter: IServiceProvider
{
   private readonly XYZServiceProvider xyzProvider;
   public XYZAdapter(XYZServiceProvider provider)
   {
      xyzProvider = provider;
   }

   public void Authenticate(string username, string password)
   {
      xyzProvider.Authenticate(username, password, GetAgentId());
   }

   public int GetAgentId()
   {
      //Retrieve the proper agent Id. It can be provided from the class creator,
      //retrieved from a known constant data source, or pulled from some factory 
      //method provided from this class's creator. Any way you slice it, consumers 
      //of this class cannot know that this information is needed.
   }
}

如果可行,则同时满足LSP和ISP;不必更改接口(interface)即可支持 LSP,因此可以防止 ISP 通常试图避免的情况(重新编译和重新分发依赖项)。但是,它增加了类数量,并强制 Adapter 中的新功能正确获取所需的 agentId,而无需依赖它通过 IServiceProvider 接口(interface)提供任何它不知道的内容。

关于oop - 接口(interface)实现(接口(interface)隔离原则),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7852418/

相关文章:

c# - 我什么时候想用私有(private) ctor 模拟一个类(class)?

c++ - 抽象类(接口(interface))中的运算符重载

c# - Activator.CreateInstance 有两个接口(interface)

c# - 将不实现接口(interface)但满足所有条件的对象添加到期望接口(interface)的列表中

c++ - 如何在 C++ 中使用智能指针实现接口(interface)隔离原则?

java - 如果 Boolean 为 True,如何返回字符串

声明为静态类成员的 C++ 类

java - Kotlin 基础继承方案

c# - 接口(interface)隔离原则是关于类还是对象?

java - 与接口(interface)隔离原则相反