我做了一个通用的界面,如:
public interface IDatabaseElement{ IList GetAll(); T Get(id); void Save(T element); void Delete(int id); }
如果我有两个元素(人和商店)只使用上述方法,那么什么是最佳实践呢?
答:为每个元素创建一个新界面,如:
public interface IPerson : IDatabaseElement{ } public interface IStore : IDatabaseElement { }
然后我的课程如下:
public class Person : IPerson { .... } public class Store : IStore { .... }
当实例化变量时:
IPerson person = new Person(); IStore store = new Store();
或者B:直接使用通用接口,如:
public class Person : IDatabaseElement{ .... } public class Store : IDatabaseElement { .... }
当实现变量时:
IDatabaseElementperson = new Person(); IDatabaseElement store = new Store();
什么是最佳做法?
你所谓的是一种已知的设计模式IDatabaseElement
; 它被称为存储库模式.所以首先重命名IDatabaseElement
为:
public interface IRepository{ ... }
此外,由于您定义了IPerson
接口,因此您似乎正在为Person
实体而不是存储库定义接口.
将您的实体隐藏在接口后面是不好的做法,因为您的实体是数据对象,接口只需要抽象行为.
因此,不是调用接口IPerson
,而是先调用它IPersonRepository
.
在另一方面,如果你的Person
类实际上包含数据(如FirstName
,LastName
,Age
,等),在这种情况下,你是混合责任.您的实体不应该知道如何从数据库中检索自己(或其他实例!!!).从数据库中检索数据并保存数据是两个不同的职责,您应该将它们分开(将每个职责分配给自己的类).如果您违反单一责任原则,您的系统很快就会变得无法维护.
现在,为每个存储库类型(例如IPersonRepository
)创建一个特定的接口是个坏主意.具有通用抽象的主要原因是因为这使得添加额外行为(例如横切关注点)变得更加容易,因为这允许您定义单个通用装饰器,例如:AuditTrailingRepositoryDecorator
.但是当你让你的人员存储库实现继承时IPersonRepository
,你不能再用通用装饰器包装它,只是因为你自己定义的所有方法IPersonRepository
都不再可访问了.这也使编写单元测试变得更加容易,因为在测试套件中,您只需要创建一个单独的通用伪实现IRepository
.
如果您对添加横切关注点以及轻松测试代码库的能力不感兴趣,可以使用特定的(非通用)接口,例如IPersonRepository
和IStoreRepository
.