Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 工厂模式创建预构建的构建器_Design Patterns - Fatal编程技术网

Design patterns 工厂模式创建预构建的构建器

Design patterns 工厂模式创建预构建的构建器,design-patterns,Design Patterns,我有一个SearchRequest对象,可以使用SearchRequestBuilder创建它。一些预定义的SearchRequestBuilder可能非常复杂。我见过工厂模式用于创建同一父对象的不同类型,但我想知道这样的设计是否合适: public class SearchRequestBuilderFactory { public enum Type { SEARCH, MATCH } public SearchRequestBuilder cre

我有一个
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;
    }
}

看起来是个好办法

也许您想封装
SearchRequestBuilder
的配置逻辑,以便

  • 更好的单元可测试性
  • 降低圈复杂度
例如:

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);
    }
}
封装配置逻辑后,可以使用映射而不是switch语句

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;
    }
}
公共类SearchRequestBuilderFactory{
公共枚举类型{
搜索、匹配
}
私有映射type2configuer=newhashmap();
公共SearchRequestBuilderFactory(){
type2configuer.put(Type.SEARCH,新的defaultSearchRequestBuilderConfigure());
type2configuer.put(Type.MATCH,new matchSearchRequestBuilderConfigure());
}
公共SearchRequestBuilder createBuilder(类型){
SearchRequestBuilderConfigurer=Type2Configuer.get(类型);
if(configurer==null){
抛出新的IllegalArgumentException(“不支持类型”+type+);
}
SearchRequestBuilder srb=新的SearchRequestBuilder();
configurer.configure(srb);
返回srb;
}
私有SearchRequestBuilder createSearchBuilder(){
SearchRequestBuilder srb=新的SearchRequestBuilder();
srb.addField(“*”);
srb.addFilter(“搜索过滤器”);
返回srb;
}
私有SearchRequestBuilder createMatchBuilder(){
SearchRequestBuilder srb=新的SearchRequestBuilder();
srb.添加过滤器(“匹配过滤器”);
srb.addThreshold(0.5);
返回srb;
}
}

PS:您也可以使用(又称虚拟构造函数)而不是配置器。

没有构建器工厂的限制。但它们并不常见是有原因的

只要对象的属性对其构造不是强制性的,我们就使用生成器。我不知道你的申请是否如此。因此,我将尝试给出一个涵盖所有场景的正确答案

场景1:某些类成员仅在特定模式下使用。在这种情况下,实际的类需要划分为不同的类。在您的情况下,如果属性阈值永远不会是搜索请求的一部分,那么它不应该是SearchRequest类的一部分,您应该有一个MatchRequest类来保存它

场景2:所有属性都在使用中,但在特定模式下,其中一些属性将具有常量值,我们永远不会对其进行外部更改。在这种情况下,我们使用不同的构建器(带有继承),而不是工厂。这将限制这些属性在外部的可访问性,这是强制性的


场景3:所有属性都在使用中,但在特定模式下,其中一些属性将具有预定义值,这些值可能会在外部发生更改。在这里,我建议使用与2相同的解决方案,因为它比使用工厂更具可读性、可维护性和可维护性。例如,在您的例子中,让我们假设传递给addField()的值需要更改为“.”,传递给addThreshold()的值需要更改为“1.5”,这样两个开发人员就可以完成这些更改,而不必接触同一个类。

看起来是一种合理的方法。