在这种情况下,我需要调用第三方服务来获取一些信息。对于不同的客户端,这些服务可以是不同的。我的接口中有一个身份验证函数,如下所示。
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}
}现在,如果我用3个参数在我的接口中提供了另一个用于身份验证的函数,并在除XYZServiceProvider之外的所有类中抛出未实现的异常,这是否违反了接口隔离原则?我在代码的其他部分也有类似的情况。谁能告诉我实现这种场景的最好方法是什么?我真的会非常感激。
发布于 2011-10-22 00:44:58
解决这个问题的最好方法可能是在接口中需要agentId,在ABC和DEF不需要它的情况下简单地忽略它。这样,消费类仍然不会知道其中的区别。
实际上,如果要互换使用ABC、DEF和XYZ提供程序,最重要的是Liskov替换原则;“给定一个由X类依赖的类A,X应该能够使用从A派生的B类,而不需要知道其中的区别”。
接口隔离原则基本上是说,接口不应该包含它的任何使用者都不需要的成员,因为如果这些成员的定义发生变化,甚至不使用该方法的类将不得不重新编译,因为它们所依赖的接口已经改变。虽然这是相关的(如果添加重载,则必须重新编译IServiceProvider的所有使用者),但如果更改了Authenticate()的签名,则无论如何都必须这样做,从维护的角度来看,更紧迫的问题是,如果添加了Authenticate()的重载,使用者现在必须知道他们需要使用哪个重载。这要求您的消费类知道公共接口的实现之间的差异,这违反了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;接口不必更改即可支持LSP,从而避免了ISP通常试图避免的情况(重新编译和重新分配依赖项)。然而,它增加了类计数,并强制适配器中的新功能正确地获取所需的agentId,而不必通过IServiceProvider接口提供它不知道的任何东西。
https://stackoverflow.com/questions/7852418
复制相似问题