【问题标题】:Interface Segregation Principle on a collection of objects对象集合上的接口隔离原则
【发布时间】:2017-11-29 01:20:34
【问题描述】:

我正在研究 SOLID 原则,而接口隔离原则让我在这样的场景中难以理解。

基本上,我有一组对象...用户...使用界面。

public interface IUserInfo 
{
    string Name { get; }
    string Extension { get; }
}

问题是在某些情况下,继承此接口的类不会使用扩展。所以为了解决这个问题,它只返回一个空字符串。

现在,从技术上讲这很好,因为字符串已绑定到 UI。所以它只会为该字段显示一个空字符串。

但是,这违反了接口隔离原则。建议拆分这些接口。

但后来我遇到了我希望在集合中使用这个接口的问题,考虑一下:

public interface IUserExtension : IUserInfo
{
    string Extension { get; }

}
    public ObservableCollection<IUserInfo> StoredUserInfos { get; set; } = new ObservableCollection<IUserInfo>()
    {
        new User1(),
        new User2(),
    };

    public class User1 : IUserExtension
    {
        public string Name { get; } = "Alex";
        public string Extension { get; } = "(715) 925";

        public override string ToString()
        {
            return Name;
        }
    }

    public class User2 : IUserInfo
    {
        public string Name { get; } = "Daniel";
        public override string ToString()
        {
            return Name;
        }
    }

我无法绑定到这个集合的索引并获取Extension,因为它是一个IUserInfo接口。巧合的是,我也无法将其设为 IUserExtension 的集合,因为 User2 类没有实现它。

据我所知,唯一可行的方法是使用模式匹配

        if (UserIndex != -1)
        {
            var userInfo = StoredUserInfos[UserIndex];
            Extension = userInfo is IUserExtension info ? info.Extension : "No Extensions";
            Name = userInfo.Name;
        }

但这会给代码增加一点复杂性,并且可能会违反其他规则,因为它正在检查类型。

在这种情况下,最好的解决方案是实现一个实现接口的抽象类,而默认实现是一个空字符串?

【问题讨论】:

标签: c# interface solid-principles


【解决方案1】:

这是一个困难的问题,但我会伸出脖子尝试回答。

在 IUserInfo 接口中包含 Extension 是否违反 ISP?我认为是和不是。

假设您想在 IUserInfo 接口中包含一个 MiddleName 属性。中间名不是每个人都有,但您可能不想将其添加到单独的界面中。与 Name 属性一起,它们是一个内聚单元,即它们属于一起。

在这种情况下,您可能希望返回一个空字符串(如上所示)或类似的。 (对于具有行为的更复杂的对象,Null Object 模式是一个更好的解决方案。)

所以,如果我们回到上面的问题,您是否认为 Extension 是属于自己的接口的东西?可能不是。同样,让我们​​想象一下将 EmailAddress 添加到 IUserInfo 接口。与 Extension 一起,它们构成了一个有凝聚力的单元,并在概念上代表了联系方式。如果您要将它们提取到一个单独的界面中,您仍然会有一些没有扩展名的用户,在这种情况下您会希望返回一个空字符串(或类似的)。

因此,在回答您的问题时,如果您不太可能使用更多属性扩展接口,我认为您可以将 Extension 保留在 IUserInfo 接口中。否则,创建一个表示联系人详细信息概念的接口,但如果用户没有扩展名,则仍返回空字符串。

【讨论】:

  • 通过几天的学习 SOLID 和设计模式,一般的规则是如果它过于复杂,你不必盲目地遵循这些原则。所以普遍的共识是保持 UserInfo 接口不变是可以的,因为它只是一个单一的属性,从技术上讲,无状态是一个有效的状态(而不是仅仅抛出一个会严重违反 ISP 的异常)
  • @Ambdex 完全正确。只有在提高可维护性时才开始有意义。
  • 在学习了设计模式和其他原理之后,这样的场景也可以通过使用桥接模式来解决。 (您在答案中描述的实际上是一种桥梁模式)。如果其他事情发生变化,这可能是最好的选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-09
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 2021-01-12
相关资源
最近更新 更多