当前位置 博文首页 > 阳阳的博客:【设计模式】建造者模式

    阳阳的博客:【设计模式】建造者模式

    作者:[db:作者] 时间:2021-08-14 21:04

    一、前言

    什么是建造者模式?或许我们对这个模式一点都不了解的。但链式调用你总写过吧,那就是建造者模式。

    我举个栗子:

    这是一个okhttp3使用的栗子:

            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .addHeader("Cookie", cookieString)
                    .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko")
                    .build();

    让我们深入Request类的内部,仅保留了url字段,简化后的Request如下:

    public final class Request {
        private final HttpUrl url;
    
        private Request(Builder builder) {
            this.url = builder.url;
        }
    
        public HttpUrl url() {
            return this.url;
        }
    
    
        public static class Builder {
            private HttpUrl url;
    
            public Builder url(HttpUrl url) {
                if (url == null) {
                    throw new NullPointerException("url == null");
                } else {
                    this.url = url;
                    return this;
                }
            }
    
            public Request build() {
                if (this.url == null) {
                    throw new IllegalStateException("url == null");
                } else {
                    return new Request(this);
                }
            }
        }
    }
    

    我们可以发现:

    1. Request类中有一个静态内部类Builder,Builder类中的属性和Request类一一对应。
    2. Request类的构造方法接收的是一个Builder对象。
    3. Builder类中每一个设置属性的方法返回值都是Builder对象本身。
    4. Builder类中的build()方法调用Request类的构造方法,将Builder对象本身传入。

    看的出来,建造者模式一步一步地将简单的对象构造成复杂的对象,我们熟悉的链式调用,就是建造者模式。

    建造者模式本来应该有多个角色:

    • Product? ? ? ? ? ? ? ? ? ?产品类,我们最终需要的产品,对应这里的Request
    • AbstractBuilder? ? ? ?抽象的建造者,规范产品的组件
    • ConcreteBuilder? ? ? 具体的建造者,实现抽象的建造者中的方法,最后返回一个产品。对应这里的Builder
    • Director? ? ? ? ? ? ? ? ? ?导演,封装了建造者,用于通知建造者开始建造

    但随着建造者模式的简化,其中的AbstractBuilder、Director的概念已经淡化,或者说用得不多。最终演变成只有一个产品类,以及产品类中的静态建造者类。


    二、实例演示

    这里我们建造一个电脑,电脑由显示器、机箱、键盘和鼠标构成。

    package com.yang.testBuilder;
    
    public class Computer {
        /**
         * 显示器
         */
        private String monitor;
    
        /**
         * 机箱
         */
        private String box;
    
        /**
         * 键盘
         */
        private String keyboard;
    
        /**
         * 鼠标
         */
        private String mouse;
    
        public Computer(Builder builder) {
            this.monitor = builder.monitor;
            this.box = builder.box;
            this.keyboard = builder.keyboard;
            this.mouse = builder.mouse;
        }
    
        public String getMonitor() {
            return monitor;
        }
    
    
        public String getBox() {
            return box;
        }
    
        public String getKeyboard() {
            return keyboard;
        }
    
        public String getMouse() {
            return mouse;
        }
    
        @Override
        public String toString() {
            return "Computer{" +
                    "monitor='" + monitor + '\'' +
                    ", box='" + box + '\'' +
                    ", keyboard='" + keyboard + '\'' +
                    ", mouse='" + mouse + '\'' +
                    '}';
        }
    
        static class Builder {
            /**
             * 显示器
             */
            private String monitor;
    
            /**
             * 机箱
             */
            private String box;
    
            /**
             * 键盘
             */
            private String keyboard;
    
            /**
             * 鼠标
             */
            private String mouse;
    
            public Builder monitor(String monitor) {
                this.monitor = monitor;
                return this;
            }
    
            public Builder box(String box) {
                this.box = box;
                return this;
            }
    
            public Builder keyboard(String keyboard) {
                this.keyboard = keyboard;
                return this;
            }
    
            public Builder mouse(String mouse) {
                this.mouse = mouse;
                return this;
            }
    
            public Computer build() {
                return new Computer(this);
            }
        }
    }
    

    测试:

    package com.yang.testBuilder;
    
    public class TestBuilderMain {
        public static void main(String[] args) {
            Computer computer = new Computer.Builder()
                    .monitor("显示器")
                    .box("机箱")
                    .keyboard("键盘")
                    .mouse("鼠标").build();
    
            System.out.println(computer);
    
        }
    }
    

    输出:

    链式调用的好处在哪里?

    链式调用比(无参构造方法+一个一个set)更加节省代码,更加简便。

    链式调用比普通的全参构造方法更加简明,全参构造方法需要将参数设置进对应的位置上,在idea中,我们需要按照ctrl+p才能显示当前参数的名称,这一点没有链式调用方便。

    cs
    下一篇:没有了