The Finder Pattern

 

Posted by   fabriziogiudici  on January 15, 2010 at 3:24 AM PST

原文地址:http://weblogs.java.net/blog/fabriziogiudici/archive/2010/01/15/finder-pattern

 

In many previous code examples in this blog I've used the “Finder pattern”, that I've elected as one of my best practices (it's standard in all my new APIs and will be retrofitted to the old ones). Before moving on with more examples, I think it's high time I shortly introduced it formally.

As the name suggests, it helps whenever you need to provide a search of some type. For instance, in the Hierarchy API the interfaces HView and HItem (name shortened from Hierarchical*** in my previous post) implement a Composite pattern, so a HItem has got children:

public interface HView
  {   
    @Nonnull
    public Finder<HItem> findChildren();
     
    @Nonnull
    public Builder<HItem> createChild();
     
    @Nonnull 
    public Builder<HItem> findOrCreateChild();
  }

public interface HItem extends HView
  {
    @Nonnull
    public HView getView();

    @Nonnull
    public HItem getParent()
      throws NotFoundException;
  }

There are many ways to search for children; for instance, you could search for a specific child with an id, or if you recall that any object in the Hierarchical API is logically bound to another object, you could explicitly search for children with a specific binding. Thus, one might need to have methods such as findChildren(), findChildById(), findChildrenBoundTo() etc. This is not a scalable approach in the perspective of flexibility, as any extension of the search facility would need the introduction of a new method. Instead, all of the above can be done with the single findChildren()returning a Finder:

HItem parent = ...;
List<? extends HItem> allChildren = parent.findChildren().results();
specificChild = parent.findChilren().withId("xyz").result();
List<? extends HItem> childrenBoundToAPhoto = parent.findChildren().boundTo(Photo.class).results();

Ok, you're probably saying that now new methods must be added to the Finder - right, I'll give more details about how to extend a Finder in another post, but in the meantime the problem has been restricted to extending a single class, instead of the many that support queries; moreover, the fact that the search responsibility is given to a specific class makes it possible to add common features without duplicating code. 

For instance, if you want to retrieve only a subset of the results (usefulr for instance with the paginated views), you can specify it:

HItem parent = ...;
List<? extends HItem> someChildren = parent.findChildren().from(10).max(20).results();
HItem the7thChildren = parent.findChildren().from(7).firstResult();
List<? extends HItem> childrenBoundToAPhoto = parent.findChildren().boundTo(Photo.class).from(10).max(30)..results();

It is possible to use a Finder just to know the number of the items that would be produced by the query:

HItem parent = ...;
int howManyChildren = parent.findChildren().count();
int howManyChildrenBoundToAPhoto = parent.findChildren().boundTo(Photo.class).count();

Depending of the implementation, asking for a count of items could generate an optimized query (e.g. a thing such as select count(*) where available). Right, because the fact that the responsibility of searching stuff is delegated to a specific class (or set of classes, as Finder acts often as a Façade pattern) makes it possible to decouple the implementation - which in a component scenario might even be pluggable, that is capable of extending functionalities by adding plugins to the system.

The fact that a Finder represents all the needed information for performing a query, but not the results of the query itself, makes it possible also to serialize it for a later retrieval (and execution), a useful feature for saved queries and such.

So, basically the Finder is a class implementing the Fluent interface pattern for specifying all the information needed to create a query (in fact you find basically the same pattern e.g. in the JPA API for creating JPAQL queries).

你可能感兴趣的:(.net,jpa,Blog)