假设出于不同的原因我想对集合进行抽象操作:
现在为了简单起见,让我们对一个集合进行推理
class Book {
public string Title { get; set; };
public string SubTitle { get; set; }
public bool IsSold { get; set; }
public DateTime SoldDate { get; set; }
public int Volums { get; set; }
}
我有一种只需要搜索Book::Title
(区分大小写或不区分大小写)的类型,因此我可以定义我的抽象:
interface ITitleSearcher {
bool ContainsTitle(string title);
}
然后实施
class CaseSensitiveTitleSearcher : ITitleSearcher { ... }
class NoCaseSensitiveTitleSearcher : ITitleSearcher { ... }
并将其作为
class TitleSearcherConsumer {
public TitleSearcherConsumer(ITitleSearcher searcher) { // <- ctor injection
}
}
直到这里我都清楚了,据我所知,接口隔离原则也得到了遵守。
继续开发我必须满足其他要求,所以我定义然后实现其他接口,ITitleSearcher
例如:
class CaseSensitiveSubTitleSearcher : ISubTitleSearcher { ... }
class SoldWithDateRangeSearcher : ISoldDateRangeSearcher { ... }
为了不违反 DRY(不要重复自己),我可以创建一个包装器IEnumerable<Book>
:
class BookCollection : ITitleSearcher, ISubTitleSearcher, ISoldDateRangeSearcher
{
private readonly IEnumerable<Book> books;
public BookCollection(IEnumerable<Book> books)
{
this.books = books;
}
//...
}
现在,如果我有一个像我这样的消费者,TitleSearcherConsumer
我可以毫无问题地传递一个BookCollection
.
但如果我有这样的消费者:
class TitleAndSoldSearcherConsumer {
public TitleAndSoldSearcherConsumer(ITitleSearcher src1, ISoldDateRangeSearcher src2) {
}
}
我无法将BookCollection
实例注入TitleAndSoldSearcherConsumer
ctor;我必须传递每个接口的实现。
是的,我可以IBookCollection
用其他接口的所有方法定义一个并在所有消费者中使用它,但是这样做不会违反 ISP 吗?
我可以同时靠近 ISP/SOLID 和 DRY 吗?