是否可以在运行时创建和执行java语句。
这样的声明:
Query q = new Query("type").setFilter(filter1).setFilter(filter2).setFilter(filter3).setFilter(filterN);
我想解决的问题是这里的Query对象是不可变的,我想在运行时基于给定的参数或参数集来构建它。
将其包含在以下方法中:
Query query = buildQueryFromArgs(type, filterList);
buildQueryFromArgs
方法本质上会在顶部创建java语句。
不能这样做:
for(Filter filter : filters){
query = query.setFilter(filter);
}
因为这里会发生的是最后一个过滤器将是唯一应用的过滤器。除非我们query.setFilter(f1).setFilter(f2).setFilter(andSoOn);
答案 0 :(得分:1)
为什么不使用Builder?
这样的事情:
QueryBuidler qb = new QueryBuilder(type);
for (Filter f : filterList)
qb = qb.setFilter(f);
Query query = qb.build();
当然,build()方法可能只调用Query的构造函数来接受Filter的类型和列表(或数组),所以也许你可以在第一时间调用该构造函数并跳过QueryBuilder类
答案 1 :(得分:1)
您有两种选择:
解决方案#1 创建一个像你说的方法。这将被视为静态工厂方法。虽然类似于构造函数,但它允许您指定标识符(名称)。虽然,如果名称不是问题,静态工厂方法可能会过于复杂;你可以只传递列表并输入构造函数。以下是静态工厂方法的示例;使用构造函数需要构造函数是非私有的:
class Query {
private List<Filter> filters;
private String type;
private Query(String type, List<Filter> filters) {
}
public static Query buildWithFilters(String type, List<Filter> filters) {
return new Query(type, filters);
}
}
然后你可以这样称呼它:
List<Filter> filters = new ArrayList<>();
//add filters
Query query = Query.buildWithFilters("type", filters);
解决方案#2 Builder pattern允许您在构建对象之前设置可选和强制对象的状态。构建之后,对象可以保持不变。
class Query {
private final String type;
private final List<Filter> filters;
private Query(Builder b) {
type = b.type;
type = b.filters;
}
private static final class Builder {
private String type;
private List<Filter> filters;
public Builder(String type) {
this.type = type;
}
public Builder addFilter(Filter filter) {
if(filters == null)
filters = new ArrayList<>();
filters.add(filter);
}
public Query build() {
return new Query(this);
}
}
}
然后你可以像这样构建你的对象:
Query query = new Query.Builder("type").addFilter(filter1).build();
这里的技巧是将状态存储在Builder
实例中,然后再将其传递给您尝试创建的实例。这允许您在创建对象之前首先指定属性,然后通过builder'a build()
方法构造具有这些属性的对象。
如果你不能修改Query
类,你的下一个选择就是创建一个不可变的包装器:
final class QueryWrapper {
private final Query query;
private final List<Filter> filters;
private QueryWrapper(Builder b) {
query = b.query;
filters = b.filters;
}
public static final class Builder {
private Query query;
private List<Filter> filters;
public Builder(Query query) {
this.query = query;
}
public Builder addFilter(Filter filter) {
if(filters == null)
filters = new ArrayList<>();
filters.add(filter);
}
public QueryWrapper build() {
new QueryWrapper(this);
}
}
}
包装器允许您封装Query
实例。客户端然后通过包装器与Query
进行通信;包装器控制可变性。
构建器允许您根据需要选择添加过滤器。包装器是不可变的,所以我们想在构造包装器之前指定可选的过滤器。构建器的构造函数强制客户端传入Query
实例(每个包装器必须有Query
)。
答案 2 :(得分:0)
看起来你问的是像
这样的东西public static Query buildQueryFromArgs(String type, List<Filter> filterList){
Query resultQuery = new Query(type);
for (Filter f : filterList){
resultQuery = resultQuery.setFilter(f);
}
return resultQuery;
}
答案 3 :(得分:0)
为什么不从SQL中获取示例并使用PreparedQuery。
使用PreparedStatements可以防止sql注入,并使查询更快。