我有一个通用的存储库模式,现在看到需要一个自定义方法来实现该模式的一个特定实现,让我们将实现称为CustomerRepository和方法GetNextAvailableCustomerNumber。我有一些想法,但它们不符合面向对象设计的SOLID原则。
我首先考虑为该实现创建一个自定义存储库模式(ICustomerRepository),但这并不是很可行。经验告诉我,目前还必须有一些我尚未考虑甚至不知道的其他方式。此外,我不认为为道路上的每一个颠簸发明一个新的存储库接口都应该轻而易举地完成。
然后,我考虑使ICustomerRepository继承IRepository 并仅添加GetNextAvailableCustomer的方法签名,但这与Liskov的Substitution Principle非常抵触,并且我相信它也与Single Responsibility Pattern略有不同。即使我只想使用ICustomerRepository,我仍然能够基于IRepository实现客户存储库。我将以两种选择结束,客户端应该实现哪个接口不再是显而易见的。在这种情况下,我希望只能实现ICustomerRepository,而不是IRepository
解决这个问题的正确方法是什么?接口继承是真正的方法吗,还是有其他首选的方法理想地符合LSP?
这是我的通用存储库接口:
public interface IRepository<T>
where T : IEntity
{
T GetById(int id);
IList<T> GetAll();
IEnumerable<T> Query(Func<T, bool> filter);
int Add(T entity);
void Remove(T entity);
void Update(T entity);
}
最佳答案
您实际上并没有违反Liskov的替代原则。里斯科夫的说
程序中的对象应可替换为其实例
子类型而不更改该程序的正确性
您可以。用对Liskov的解释,几乎不允许类的继承和扩展。
我认为从IRepository“继承”的ICustomerRepository很好。我仍然可以在使用IRepostory的任何地方替换ICustomerRepository(鉴于ICustomerRepository:IRepostory)
Liskov防范子类的意外行为。最常用(尽管不一定是最好的)示例似乎是来自矩形的方形印章的示例。在这里,我们有一个SetWidth方法,该方法被Square覆盖,但Square也可以设置高度,因为它是一个正方形。因此,原始方法的定义在子类中更改,因此违反了原理。