我有一个SearchRequest
对象,可以使用SearchRequestBuilder
创建。我们的一些预定义SearchRequestBuilder
可能非常复杂。我已经看到工厂模式用于创建相同父对象的不同类型,但我想知道这是否适当的设计有这样的东西:
public class SearchRequestBuilderFactory {
public enum Type {
SEARCH, MATCH
}
public SearchRequestBuilder createBuilder(Type type) {
switch (type) {
case SEARCH:
return createSearchBuilder();
break;
case MATCHING:
return createMatchBuilder();
break;
}
}
private SearchRequestBuilder createSearchBuilder() {
SearchRequestBuilder srb = new SearchRequestBuilder();
srb.addField("*");
srb.addFilter("searchFilter");
return srb;
}
private SearchRequestBuilder createMatchBuilder() {
SearchRequestBuilder srb = new SearchRequestBuilder();
srb.addFilter("matchFilter");
srb.addThreshold(0.5);
return srb;
}
}
答案 0 :(得分:2)
没有建设工厂的限制。但是他们出于某种原因并不常见......
只要对象的属性对其构造不是强制性的,我们就使用Builder。我不知道你的申请是否属实。因此,我将尝试给出一个涵盖所有场景的正确答案。
情景1:某些班级成员仅在特定模式下使用。在这种情况下,实际的课程需要分为不同的课程。在您的情况下,如果属性阈值永远不会成为搜索请求的一部分,那么它不应该是SearchRequest类的一部分,并且您应该有一个MatchRequest类来保存它。
情景2:所有属性都在使用中,但在某种模式下,其中一些属性将具有常量值,我们永远不会在外部更改。在这种情况下,我们使用不同的构建器(具有继承)而不是工厂。这将限制外部这些属性的可访问性,这是必需的。
情景3:所有属性都在使用中,但在某种模式下,其中一些属性具有预定义值,可能会在外部发生变化。在这里,我建议使用与2相同的解决方案,因为它比使用工厂更具可读性,可维护性和SRP。因此,例如在您的情况下,假设传递给addField()的值需要更改为“。”,并且传递给addThreshold()的值需要更改为“1.5”,而不是两个开发人员可以完成这些变化无需触及同一课程。
答案 1 :(得分:0)
看起来是一个很好的方法。
也许您想要封装interface SearchRequestBuilderConfigurer {
public void configure(SearchRequestBuilder srb);
}
class DefaultSearchRequestBuilderConfigurer implements SearchRequestBuilderConfigurer {
public void configure(SearchRequestBuilder srb){
srb.addField("*");
srb.addFilter("searchFilter");
}
}
class MatchSearchRequestBuilderConfigurer implements SearchRequestBuilderConfigurer {
public void configure(SearchRequestBuilder srb){
srb.addFilter("matchFilter");
srb.addThreshold(0.5);
}
}
的配置逻辑以便
例如:
public class SearchRequestBuilderFactory {
public enum Type {
SEARCH, MATCH
}
private Map<Type, SearchRequestBuilderConfigurer> type2Configurer = new HashMap<Type, SearchRequestBuilderConfigurer>();
public SearchRequestBuilderFactory(){
type2Configurer.put(Type.SEARCH, new DefaultSearchRequestBuilderConfigurer());
type2Configurer.put(Type.MATCH, new MatchSearchRequestBuilderConfigurer());
}
public SearchRequestBuilder createBuilder(Type type) {
SearchRequestBuilderConfigurer configurer = type2Configurer.get(type);
if(configurer == null){
throw new IllegalArgumentException("type " + type + " is not supported");
}
SearchRequestBuilder srb = new SearchRequestBuilder();
configurer.configure(srb);
return srb;
}
private SearchRequestBuilder createSearchBuilder() {
SearchRequestBuilder srb = new SearchRequestBuilder();
srb.addField("*");
srb.addFilter("searchFilter");
return srb;
}
private SearchRequestBuilder createMatchBuilder() {
SearchRequestBuilder srb = new SearchRequestBuilder();
srb.addFilter("matchFilter");
srb.addThreshold(0.5);
return srb;
}
}
封装配置逻辑后,您可以使用map而不是switch语句。
for (int i = 1; i < 11; i++) {
if (Math.abs(number) < (j = Math.pow(10, i))) {
System.out.println("Number of Digits : "+i);
break;
}
}
PS:您还可以使用facotry method pattern(又称虚拟构造函数)代替配置程序。