NoSQL
发布时间:2022-05-24 发布网站:大佬教程 code.js-code.com
大佬教程收集整理的这篇文章主要介绍了设计模式系列:仓储模式,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
仓储模式的实现@H_616_2@@H_404_3@
仓储Repository模式已经成为最主流的模式,数据库持久化很长时间以来是一个讨论热点,目前主要问题是:主流软件并不容易有效地将需要存储的数据映射到外部存储空间如关系数据库或NoSQL@H_616_2@数据库。
技术难点虽然已经被一些ORM工具如Hibernate等解决了,过去,我们通常使用DAO或ORM来进行业务对象和持久化数据表之间进行转换,这些技术很好,但是他们还是属于底层技术,并不能透明地和我们统一语言整合。下面的问题是如何将持久化动作和对象获取方式以及领域模型Domain Model结合起来,更进一步地说:如何更加统一我们的语言(Ubiquitous LanguagE)(不至于出现Hibernate等底层技术语言,统一为业务语言)。
一个整合持久化技术的好办法是仓储RepositorIEs,在Evans书籍中定义它是:一种机制,用于封装存储获取搜寻一群对象集合等行为。这个定义很容易向领域专家解释,整合到统一语言中。
第一:命名
一般人仓储类如下命名:@H_404_3@
class@H_616_2@ OrderRepository { List<Order> getordersFor(Account a){...} }@H_404_3@
|
而Rodrigo Yoshima 认为应该如下取名:@H_404_3@
class@H_616_2@ Allorders { List<Order> belongingTo(Account a){...} }@H_404_3@
|
似乎是一个小的改变,但是有帮助得多,如果两个仓储包含不属于他们的方法,我们如何分辨他们呢?@H_404_3@
//classic naming style@H_616_158@ class@H_616_2@ UserRepository{ User retrIEveUserByLogin(String login){...} voID@H_616_2@ submitOrder(Order order){...} }@H_404_3@
|
客户端调用代码:@H_404_3@
User u = userRepository.retrIEveUserByLogin(“pcalcado”); userRepository.submitOrder(new@H_616_2@ Order());@H_404_3@
|
而Yoshima的取名方式如下:@H_404_3@
//Yoshima’s naming style@H_616_158@ class@H_616_2@ AllUsers{ User withLogin(String login){...} voID@H_616_2@ submitOrder(Order order){...} } //clIEnt code //非常符合英语风格,象说话一样。@H_616_158@ User u = allusers.withLogin(“pcalcado”); allusers.submitOrder(new@H_616_2@ Order());@H_404_3@
|
一定要记住:你使用的语言方式会影响你如何思考。以retrIEve或get为开始方法名是坏味道。
第二:避免方法爆炸
一个好的仓储将领域概念建模在其接口中,让我们看一个业务规则:
每个订单在周末都要增加10%的附加费。
如果我们要显示所有订单,如下:@H_404_3@
这虽然工作很好,但是忘记了抽象,增加附加费这个规则是不应该暴露给调用客户端的,如下会更好些:
return allorders.surchargedFor(user);
为了实现这点,可能需要多个实体反复查询,你可以使用规格模式Specification来实现,如下:
Specification surcharged = specifications.surcharged();
return allorders.thatAre(user,surchanged);
如果我们要获取没有附加费或者有附加费的订单,需要两个仓储Allorders 和 Surchargedorders.如下:@H_404_3@
Subset RepositorIEs子集仓储一般被建模成带有参数实例的仓储类,如下:@H_404_3@
//a base Repository@H_616_158@ class@H_616_2@ Users { private@H_616_2@ User.Status desiredStatus = null@H_616_2@; public@H_616_2@ Users(){ this@H_616_2@(User.Status.ANY); } public@H_616_2@ Users(User.Status desiredStatus){ this@H_616_2@.desiredStatus= desiredStatus; } //methods go here...@H_616_158@ } //instantiated somewhere as@H_616_158@ private@H_616_2@ Users allUsers = new@H_616_2@ Users(); private@H_616_2@ Users activeUsers = new@H_616_2@ Users(User.Status.ACTIVE); private@H_616_2@ Users inactiveUsers = new@H_616_2@ Users(User.Status.INACTIVE);@H_404_3@
|
第三:只有一个类型
如下代码,虽然使用了好的命名规则@H_404_3@
方法返回了service类型集合,还返回了Product集合,是多个集合,好的设计最好返回同一个类型集合:@H_404_3@
如果特别情形需要,你可以创建一个Wrapper类,将这些方法都放入其中,如下:@H_404_3@
public class@H_616_2@ BillingSystemGateway implements Allservices,AllProducts,AllContractDetails { List<service> belongingTo(List<Account> accounts){...} service withnumber(String servicenumber) {...} List<service> relatedTo(service otherservicE) {...} List<Product> activeBelongingTo(List<Account> accounts) {...} List<Product> belongingTo(List<Account> accounts) {...} ContractDetails forservicenumber(String servicenumber) {...}@H_404_3@
|
@H_616_2@最后:仓储不只是持久,仓储经常用于对象存储持久化,但是这不一定是这种情况,也适合于系统整合,甚至简单内存@H_616_2@缓存中集合返回值对象等等。@H_616_2@
@H_616_2@一定要记住:仓储好处是高调说明对象来自某个地方,将这些对象作为统一语言的一部分,仓储尽可能贴近我们的领域模型。@H_616_2@@H_404_3@大佬总结
以上是大佬教程为你收集整理的设计模式系列:仓储模式全部内容,希望文章能够帮你解决设计模式系列:仓储模式所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。