由于各种原因,我们正在编写一个新的业务对象/数据存储库。该层的要求之一是将业务规则的逻辑与实际的数据存储层分开。
可以有多个数据存储层来实现对同一个对象的访问——例如,实现大多数对象的主“数据库”数据存储源,以及实现用户对象的另一个“ldap”源。在这种情况下,用户可以选择来自 LDAP 源,可能具有稍微不同的功能(例如,无法保存/更新用户对象),但应用程序以相同的方式使用它。另一种数据存储类型可能是 Web 服务或外部数据库。
我们正在考虑通过两种主要方式来实现这一点,我和一位同事在基本层面上存在分歧,这是正确的。我想就哪一个最好用一些建议。我会尽量保持对每一个的描述尽可能中立,因为我在这里寻找一些客观的观点。
业务对象是基类,数据存储对象继承业务对象。客户端代码处理数据存储对象。
在这种情况下,每个数据存储对象都继承了通用的业务规则,而客户端代码直接使用的是数据存储对象。
这意味着客户端代码确定对给定对象使用哪种数据存储方法,因为它必须显式声明该类型对象的实例。客户端代码需要明确知道它使用的每种数据存储类型的连接信息。
如果数据存储层为给定对象实现不同的功能,客户端代码在编译时明确知道它,因为对象看起来不同。如果数据存储方式发生变化,客户端代码也必须更新。
业务对象封装了数据存储对象。
在这种情况下,业务对象直接由客户端应用程序使用。客户端应用程序将基本连接信息传递给业务层。由业务对象代码决定给定对象使用哪种数据存储方法。连接信息将是从配置文件中获取的一大块数据(客户端应用程序并不真正了解/关心它的细节),它可能是数据库的单个连接字符串,也可能是各种数据存储类型的多个连接字符串。其他数据存储连接类型也可以从另一个位置读取 - 例如,数据库中的配置表指定各种 Web 服务的 URL。
这样做的好处是,如果将新的数据存储方法添加到现有对象,则可以在运行时设置配置设置以确定使用哪种方法,并且对客户端应用程序完全透明。如果给定对象的数据存储方法发生更改,则无需修改客户端应用程序。
业务对象是基类,数据源对象继承自业务对象。客户端代码主要处理基类。
这与第一种方法类似,但客户端代码声明了基本业务对象类型的变量,并且业务对象上的 Load()/Create()/etc 静态方法返回适当的数据源类型对象。
此解决方案的架构与第一种方法类似,但主要区别在于为给定业务对象使用哪个数据存储对象由业务层而非客户端代码决定。
我知道已经有现有的 ORM 库提供了一些这样的功能,但现在请打折扣(数据存储层有可能是用这些 ORM 库之一实现的) - 另请注意,我故意不告诉你这里使用的是什么语言,除了它是强类型的。
我在这里寻找一些关于哪种方法更好使用(或随意提出其他建议)以及原因的一般建议。