接口隔离原则 - 如何决定隔离什么?

时间:2016-06-17 18:43:54

标签: c# interface-segregation-principle

我认为这个问题是自我解释的。我宁愿把更多的注意力放在支持问题的例子上。

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

public interface ICollection : IEnumerable
{
    void CopyTo(Array array, int index);
    int Count { get; }
    Object SyncRoot { get; }
    bool IsSynchronized { get; }
}

public interface IList : ICollection
{
    Object this[int index] { get; set; }
    int Add(Object value);
    bool Contains(Object value);
    void Clear();
    bool IsReadOnly { get; }
    bool IsFixedSize { get; }
    int IndexOf(Object value);
    void Insert(int index, Object value);
    void Remove(Object value);
    void RemoveAt(int index);
}

很明显,IEnumerable是独立的,只允许循环集合。但我不明白为什么他们将ICollectionIList分开?即使它们是一个,IList也不会变胖,因为任何集合都需要这种行为?

我发现了this帖子,其中说如果客户端只需要循环项目,IEnumerable,如果只需要只读访问权限,那么您的API将返回ICollection,等等。< / p>

MSFT如何完美地应用ISP,这些年来从未引起任何问题?

是否根据客户端代码需求或一次性应用程序向ISP申请持续流程?如果ISP只应用一次,那么我的问题就在帖子标题中。

1 个答案:

答案 0 :(得分:2)

  

我不明白为什么他们将ICollectionIList分开?

IList是一个集合,通过索引获取项目具有逻辑意义。将其分离成子接口是为了认识到存在其他索引未定义的集合的事实。 ISet就是此类收集的一个例子。

合并ICollectionIList会对一个人以干净的方式定义ISet的能力产生负面影响,因为必须实施这四种方法:

this[int index]
int IndexOf(Object value)
void Insert(int index, Object value)
void RemoveAt(int index)

另一方面,人们可以合理地论证方法

int Add(Object value);
bool Contains(Object value);
void Clear();
bool IsReadOnly { get; }
bool IsFixedSize { get; }
void Remove(Object value);

可能属于ICollection界面。

  

接口隔离原则 - 如何决定隔离什么?

当课程到位时,回想起来决定分离什么的任务要容易得多。查看是否需要任何类来抛出未实现的异常。这些方法是移动到需要引入的子接口的主要候选者。

例如,考虑开始使用IList方法移入ICollection,而不是IList子接口的设计。您可以使用这两个接口成功构建ListLinkedList类。

现在考虑在混合中添加HashSet。这个类必须使用set集合实现四个不合适的方法,这表明你应该考虑添加一个或两个子接口 - 一个用于列表,另一个用于集合。

在你有任何类之前决定隔离是很困难的,因为你的界面往往满足需要使用它的特定类的需要。从平面接口结构开始并通过后续版本中的重构扩展它并不罕见。