【发布时间】:2010-08-24 02:02:28
【问题描述】:
注意:请忽略我使用 <i>MultivaluedMap</i> 而不是多个 vargs String...args。
java中有标准的方法吗?
我拥有的是从远程服务器返回的资源。但是在每次查询之前,远程连接必须打开,并且在返回返回之后 - 它必须关闭。
所以一个自然的方式是这样的:
Connection c = config.configureConnection();
c.open(); //open
List<Car> cars;
try{
cars = c.getCars();
}finally{
c.close(); //close
}
现在我想实现一些在资源本身级别上运行的东西,而不用担心连接,例如:
List<Car> cars = new CarResource().all(); //opens and closes connection
我目前的做法是拥有一个抽象类,AbstractQueriable 调用抽象方法 query(String ...args) 和 query(int id),任何扩展它的类都必须实现。
AbstractQuerieable 实现了 Queriable 接口,这使得它暴露了三个公共方法 filter(String ...args), all() 和 get(int id) - 这是面向公众的方法。
这里是查询接口:
public interface Queriable <T>{
public T get(String id);
/** Simply returns all resources */
public Collection<T> all();
public Collection<T> filter(MultivaluedMap<String, String> args);
}
这是实现它的 AbstractQueriable 类:
public abstract class AbstractQueriable<T> implements Queriable<T> {
@Override
public final T get(String id) {
setup();
try {
return query(id);
} finally {
cleanup();
}
}
@Override
public final Collection<T> filter(MultivaluedMap<String, String> args) {
setup();
try {
return query(args);
} finally {
cleanup();
}
}
/**
* Returns all resources.
*
* This is a convenience method that is equivalent to passing an empty
* arguments list to the filter function.
*
* @return The collection of all resources if possible
*/
@Override
public final Collection<T> all() {
return filter(null);
}
/**
* Queries for a resource by id.
*
* @param id
* id of the resource to return
* @return
*/
protected abstract T query(String id);
/**
* Queries for a resource by given arguments.
*
* @param args
* Map of arguments, where each key is the argument name, and the
* corresponing values are the values
* @return The collection of resources found
*/
protected abstract Collection<T> query(MultivaluedMap<String, String> args);
private void cleanup() {
Repository.close();
}
private void setup() {
Repository.open();
}
最后,我想在代码中使用的资源必须扩展 AbstractQueriable 类,例如(请注意,这些方法的细节并不重要):
public class CarRepositoryResource extends AbstractQueriable<Car> {
@Override
protected Car query(String id) {
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("CarID", id);
// Delegate the query to the parametarized version
Collection<cars> cars = query(params);
if (cars == null || cars.size() == 0) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
if (cars.size() > 1) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return cars.iterator().next();
}
@Override
protected Collection<Car> query(MultivaluedMap<String, String> params) {
Collection<Car> cars = new ArrayList<Car>();
Response response = Repository.getConnection().doQuery("Car");
while (response.next()) {
Returned returned = response.getResult();
if (returned != null) {
cars.add(returned);
}
}
return cars;
}
}
最后,我可以在我的代码中使用:
Collection<Car> cars = new CarRepositoryResource().all();
//... display cars to the client etc...
我不喜欢这种设置:
- 每次执行查询时,我都必须实例化我的“CarRepositoryResource”的一个新实例。
- 方法名称“query”虽然是内部的和私有的,但仍然令人困惑和笨拙。
- 我不确定是否有更好的模式或框架。
我使用的连接不支持/实现 JDBC api 并且不是基于 sql 的。
【问题讨论】:
-
您可以考虑使用 AOP 或代理来透明地处理连接,例如使用 Spring 或(可能)Guice。
-
谢谢,我实际上正在寻找一些类似的建议。你能用一些好的起点把它变成一个答案吗?
标签: java design-patterns