• 建造者模式


    建造者模式

    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"}
    
  • 相关阅读:
    嵌入式Qt4.7.1安装详解
    oracle数据库、客户端安装以及ps/sql连接和导入表实例
    大战C100K之-Linux内核调优篇--转载
    读<阿里亿级日活网关通道架构演进>有感
    hadoop跑第一个实例过程
    Using the command line to manage files on HDFS--转载
    hadoop命令帮助
    从netty-example分析Netty组件续
    windows下spark开发环境配置
    源码分析netty服务器创建过程vs java nio服务器创建
  • 原文地址:https://www.cnblogs.com/yslu/p/15798818.html
Copyright © 2020-2023  润新知