zoukankan      html  css  js  c++  java
  • 建造者模式

    建造者模式

    1.锚定对应的源码

    在springMVC中的使用,在springMVC项目的tomcat启动时,项目会创建请求映射集合,就是RequestMapping集合,在这个过程中会调用createRequestMappingInfo(method)方法创建RequestMappingInfo对象,

    image-20220113161027175

    2.注意createRequestMappingInfo方法

    createRequestMappingInfo方法,可以看到使用链式调用传入需要的参数最后调用build()快速创建对象。

    protected RequestMappingInfo createRequestMappingInfo(
          RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
    
       RequestMappingInfo.Builder builder = RequestMappingInfo
             .paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
             .methods(requestMapping.method())
             .params(requestMapping.params())
             .headers(requestMapping.headers())
             .consumes(requestMapping.consumes())
             .produces(requestMapping.produces())
             .mappingName(requestMapping.name());
       if (customCondition != null) {
          builder.customCondition(customCondition);
       }
       return builder.options(this.config).build();
    }
    

    3.观察RequestMappingInfo

    1.再来看看RequestMappingInfo这个类,可以看到定义了8个变量

    public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
    
       @Nullable
       private final String name;
    
       private final PatternsRequestCondition patternsCondition;
    
       private final RequestMethodsRequestCondition methodsCondition;
    
       private final ParamsRequestCondition paramsCondition;
    
       private final HeadersRequestCondition headersCondition;
    
       private final ConsumesRequestCondition consumesCondition;
    
       private final ProducesRequestCondition producesCondition;
    
       private final RequestConditionHolder customConditionHolder;
    
    
       public RequestMappingInfo(@Nullable String name, @Nullable PatternsRequestCondition patterns,
             @Nullable RequestMethodsRequestCondition methods, @Nullable ParamsRequestCondition params,
             @Nullable HeadersRequestCondition headers, @Nullable ConsumesRequestCondition consumes,
             @Nullable ProducesRequestCondition produces, @Nullable RequestCondition<?> custom) {
    
          this.name = (StringUtils.hasText(name) ? name : null);
          this.patternsCondition = (patterns != null ? patterns : new PatternsRequestCondition());
          this.methodsCondition = (methods != null ? methods : new RequestMethodsRequestCondition());
          this.paramsCondition = (params != null ? params : new ParamsRequestCondition());
          this.headersCondition = (headers != null ? headers : new HeadersRequestCondition());
          this.consumesCondition = (consumes != null ? consumes : new ConsumesRequestCondition());
          this.producesCondition = (produces != null ? produces : new ProducesRequestCondition());
          this.customConditionHolder = new RequestConditionHolder(custom);
       }
    

    在这个对象类中定义了builder内部接口,同时DefaultBuilder实现了builder接口,里面都是对DefaultBuilder对象的赋值

    image-20220113161349329

    最后调用build()方法,返回RequestMappingInfo对象,完成对象的赋值操作。

    @Override
    public RequestMappingInfo build() {
       ContentNegotiationManager manager = this.options.getContentNegotiationManager();
    
       PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
             this.paths, this.options.getUrlPathHelper(), this.options.getPathMatcher(),
             this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
             this.options.getFileExtensions());
    
       return new RequestMappingInfo(this.mappingName, patternsCondition,
             new RequestMethodsRequestCondition(this.methods),
             new ParamsRequestCondition(this.params),
             new HeadersRequestCondition(this.headers),
             new ConsumesRequestCondition(this.consumes, this.headers),
             new ProducesRequestCondition(this.produces, this.headers, manager),
             this.customCondition);
    }
    

    思考:

    为什么要用建造者模式,如果不用会怎么样?

    从源码中可以发现,使用建造者模式,在创建对象的时候,只需要传入需要的参数即可,一行代码便可完成对象的创建,简洁方便

    什么是链式调用,原理是什么?优点在哪里?

    RequestMappingInfo
             .paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
             .methods(requestMapping.method())
             .params(requestMapping.params())
             .headers(requestMapping.headers())
             .consumes(requestMapping.consumes())
             .produces(requestMapping.produces())
             .mappingName(requestMapping.name());
    

    不断的.参数.参数.参数就是链式调用。其本质原理是在第一次.path的时候new Defaultbuilder返回这个静态内部类对象,后续调用这个静态内部类的方法,且每次返回这个第一次new出来的对象,所以可以不断的调用,再最后调用build()方法,这个方法里就是将Defaultbuilder接受到的参数再调用RequestMappingInfo对象全参的构造方法最后对象。

    这里模仿这种方式自己创建了一个user类模拟这个建造者方式

    实战:

    创建建造者模式的User

    package DesignPattern.builder;
    
    import lombok.Data;
    
    @Data
    public class User {
        private String name;
        private String code;
    
        public User(String name, String code) {
            this.name = name;
            this.code = code;
        }
    
        public interface Builder {
            Builder name(String name);
    
            Builder code(String name);
    
            User build();
        }
    
        public static Builder start() {
            return new DefaultBuilder();
        }
    
        private static class DefaultBuilder implements Builder {
            private String name;
            private String code;
    
            @Override
            public DefaultBuilder name(String name) {
                this.name = name;
                return this;
            }
    
            @Override
            public DefaultBuilder code(String code) {
                this.code = code;
                return this;
            }
    
            @Override
            public User build() {
                return new User(this.name, this.code);
            }
        }
    
    }
    

    测试调用:

    User.Builder user1 = User.start().code("test1").name("测试1");
    User user2 = user1.build();
    User user3 = User.start().code("test3").name("测试3").build();
    User user4 = User.start().code("test4").build();
    User user5 = User.start().name("测试5").build();
    System.out.println(JSON.toJSONString(user1));
    System.out.println(JSON.toJSONString(user2));
    System.out.println(JSON.toJSONString(user3));
    System.out.println(JSON.toJSONString(user4));
    System.out.println(JSON.toJSONString(user5));
    

    控制台输出:

    image-20220113181051389

    拓展知识:

    lombok的@builder注解可以起到同样的作用,再定义完类后,在类标签加上这个注解即可

    举个栗子:

    @Builder
    @Data
    public class Student {
        private String name;
        private String code;
    
        public static void main(String[] args) {
            Student student = Student.builder().code("11").name("lys").build();
            System.out.println(JSON.toJSONString(student));
        }
    }
    

    控制台出:

    {"code":"11","name":"lys"}
    
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/yslu/p/15798818.html
Copyright © 2011-2022 走看看