我试图理解“查询对象设计模式”。我无法找到好的和简单的例子。有人可以帮我理解这个设计模式是什么以及我们可以实现这个问题吗?
答案 0 :(得分:32)
Query设计模式通常与Repository设计模式结合使用。
让我们举个例子,然后我会给你一篇很好的文章。我们假设我们有一个数据库,用于存储有关客户及其订单等的信息。
然后我们创建一个这样的初始存储库:
class CustomerRepository() {
Customer GetById(int id) { // implementation }
void DeleteCustomer(int id) { // impl }
Customer GetCustomerWithOrder(int orderId);
Customer[] GetCustomersWithOrdersMoreThan(int numberOfOrders);
}
正如您在每个查询中看到的那样,我们在存储库中创建了一个非常精细且适用于有限数量查询的方法,但是当我们有很多查询并且他们开始变得很复杂时会有很多组合(例如,让我的客户购买超过1000并且住在纽约并且他们的信用额度低于3000)那么我们最终会得到一长串方法,更糟糕的是,泄漏一些业务逻辑的形式在我们不希望发生的存储库内查询。
所以要重构我们将存储库更改为这样的东西:
class CustomerRepository() {
Customer[] Get(Query query) { // implementation }
void DeleteCustomer(int id) { // impl }
}
正如您所看到的,我们正在传递一个查询对象,它以对象的形式表示我们的查询,并且存储库有一个唯一的存储库来执行该查询并将结果返回给我们。 / p>
现在如何实现查询对象以及如何构建它将需要大量代码,所以此时我将引导您到这个nice article。它位于C#中,但您会发现它非常有用,您也可以查看NHibernate使用的Criteria API( Java )来查看不同但相似的实现。
答案 1 :(得分:6)
查询对象表示以域语言编写的查询,并且是查询对象模式的实现。 Fowler描述的查询对象模式是“表示数据库查询的对象。”如果没有某种查询机制,存储库将充斥着无数的检索方法,例如可以在此代码片段中看到:
public interface ICustomerRepository
{
IEnumerable<Customer> FindAll();
IEnumerable<Customer> FindAllVIPCustomers();
IEnumerable<Customer> FindByOrder(Guid ID);
IEnumerable<Customer> FindAllCustomersThatHaveOutstandingOrders();
…
}
相反,查询对象允许构造任何查询,然后发送到存储库以满足。查询对象模式的主要好处是它完全抽象出底层数据库查询语言,从而将数据持久性和检索的基础结构问题保留在业务层之外。但是,在某些时候,需要创建数据库的原始查询语言;这是使用特定于数据库的QueryTranslator实现的,该QueryTranslator接受查询对象并将它们转换为数据库的语言。
来自Pro ASP.NET Design Patterns一书。
答案 2 :(得分:0)
看看我为NHibernate编写的查询对象模式库:https://github.com/shaynevanasperen/NHibernate.Sessions.Operations