设计模式之禅(四):建造者模式,简易版建造者,JDK 中的StringBuilder,建造者和工厂方法的区别。

𝑰’𝒎 𝒉𝒉𝒈, 𝑰 𝒂𝒎 𝒂 𝒈𝒓𝒂𝒅𝒖𝒂𝒕𝒆 𝒔𝒕𝒖𝒅𝒆𝒏𝒕 𝒇𝒓𝒐𝒎 𝑵𝒂𝒏𝒋𝒊𝒏𝒈, 𝑪𝒉𝒊𝒏𝒂.

  • 🏫 𝑺𝒉𝒄𝒐𝒐𝒍: 𝑯𝒐𝒉𝒂𝒊 𝑼𝒏𝒊𝒗𝒆𝒓𝒔𝒊𝒕𝒚
  • 🌱 𝑳𝒆𝒂𝒓𝒏𝒊𝒏𝒈: 𝑰’𝒎 𝒄𝒖𝒓𝒓𝒆𝒏𝒕𝒍𝒚 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒅𝒆𝒔𝒊𝒈𝒏 𝒑𝒂𝒕𝒕𝒆𝒓𝒏, 𝑳𝒆𝒆𝒕𝒄𝒐𝒅𝒆, 𝒅𝒊𝒔𝒕𝒓𝒊𝒃𝒖𝒕𝒆𝒅 𝒔𝒚𝒔𝒕𝒆𝒎, 𝒎𝒊𝒅𝒅𝒍𝒆𝒘𝒂𝒓𝒆 𝒂𝒏𝒅 𝒔𝒐 𝒐𝒏.
  • 💓 𝑯𝒐𝒘 𝒕𝒐 𝒓𝒆𝒂𝒄𝒉 𝒎𝒆:𝑽𝑿
  • 📚 𝑴𝒚 𝒃𝒍𝒐𝒈: 𝒉𝒕𝒕𝒑𝒔://𝒉𝒉𝒈𝒚𝒚𝒅𝒔.𝒃𝒍𝒐𝒈.𝒄𝒔𝒅𝒏.𝒏𝒆𝒕/
  • 💼 𝑷𝒓𝒐𝒇𝒆𝒔𝒔𝒊𝒐𝒏𝒂𝒍 𝒔𝒌𝒊𝒍𝒍𝒔:𝒎𝒚 𝒅𝒓𝒆𝒂𝒎

1-1:定义

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations.
建造者设计模式是为了把复杂对象的创建从它的表示中分离出来,这样的话,同样的构造过程能够创建出不同的表示。

在这里插入图片描述

1-2:传统建造者模式

还是老样子,先给demo,再分析他的好坏。
在这里插入图片描述

  • Bike
    package com.company.design.builder.traditional;
    
    public class Bike {
        private String componentA;
        private String componentB;
        private String componentC;
    
        public Bike() {
        }
    
        public void setComponentA(String componentA) {
            this.componentA = componentA;
        }
    
        public void setComponentB(String componentB) {
            this.componentB = componentB;
        }
    
        public void setComponentC(String componentC) {
            this.componentC = componentC;
        }
    
        @Override
        public String toString() {
            return "Bike{" +
                    "componentA='" + componentA + '\'' +
                    ", componentB='" + componentB + '\'' +
                    ", componentC='" + componentC + '\'' +
                    '}';
        }
    }
    
  • Builder
    package com.company.design.builder.traditional;
    
    public abstract class Builder {
        protected abstract void buildComponentA();
    
        protected abstract void buildComponentB();
    
        protected abstract void buildComponentC();
    
        protected abstract Bike createBike();
    }
    
  • HaloBuilder
    package com.company.design.builder.traditional;
    
    public class HaloBuilder extends Builder {
        private Bike haloBike = new Bike();
    
        @Override
        protected void buildComponentA() {
            this.haloBike.setComponentA("halo componentA");
        }
    
        @Override
        protected void buildComponentB() {
            this.haloBike.setComponentB("halo componentB");
        }
    
        @Override
        protected void buildComponentC() {
            this.haloBike.setComponentC("halo componentC");
        }
    
        @Override
        protected Bike createBike() {
            return this.haloBike;
        }
    }
    
  • OfOBuilder
    package com.company.design.builder.traditional;
    
    public class OfOBuilder extends Builder {
        private Bike ofoBike = new Bike();
    
        @Override
        protected void buildComponentA() {
            this.ofoBike.setComponentA("ofo componentA");
        }
    
        @Override
        protected void buildComponentB() {
            this.ofoBike.setComponentB("ofo componentB");
        }
    
        @Override
        protected void buildComponentC() {
            this.ofoBike.setComponentC("ofo componentC");
        }
    
        @Override
        protected Bike createBike() {
            return this.ofoBike;
        }
    }
    
  • Director
    package com.company.design.builder.traditional;
    
    public class Director {
        private Builder haloBikeBuilder = new HaloBuilder();
        private Builder OfOBikeBuilder = new OfOBuilder();
    
        public Bike getHaloBike() {
            this.haloBikeBuilder.buildComponentA();
            this.haloBikeBuilder.buildComponentB();
            return haloBikeBuilder.createBike();
        }
    
        public Bike getOfOBike() {
            this.OfOBikeBuilder.buildComponentA();
            this.OfOBikeBuilder.buildComponentC();
            return OfOBikeBuilder.createBike();
        }
    }
    
  • Client
    package com.company.design.builder.traditional;
    
    public class Client {
        public static void main(String[] args) {
            Director director = new Director();
            Bike haloBike = director.getHaloBike();
            Bike ofOBike = director.getOfOBike();
            System.out.println(haloBike);
            System.out.println(ofOBike);
        }
    }
    

简单分析一下这里的代码:一句话概括指挥者director指挥builder去执行build 产品操作。

  • director把builder的建造流程进行了封装,也就是说本来builder四散在外面一个产品一个builder,director将他们汇聚起来了,实际的建造过程还是builder去做的,那么director是负责制造的顺序,哪些要调用,哪些不要,可以自由选择。
  • 关于builder的写法:我感觉我这样写的话,其实也没啥问题,意思是一个意思吧,只是顺序交给了builder去定,而不是director定顺序。
    - director
    public Bike geHaloBike() {
        return haloBikeBuilder.createBike();
    }
    - Halobuilder
    @Override
    protected Bike createBike() {
        this.haloBike.setComponentA("halo componentA");
        this.haloBike.setComponentB("halo componentB");
        return this.haloBike;
    }
    

1-3:简化的建造者-链式写法的由来?

先上代码,再分析:

package com.company.design.builder.simple;

public class Bike {
    private String componentA;
    private String componentB;
    private String componentC;

    private Bike(Builder builder) {
        this.componentA = builder.componentA;
        this.componentB = builder.componentB;
        this.componentC = builder.componentC;
    }


    public static final class Builder {
        private String componentA;
        private String componentB;
        private String componentC;

        public Builder() {
        }

        public Builder setComponentA(String componentA) {
            this.componentA = componentA;
            return this;
        }

        public Builder setComponentB(String componentB) {
            this.componentB = componentB;
            return this;
        }

        public Builder setComponentC(String componentC) {
            this.componentC = componentC;
            return this;
        }

        public Bike build() {
            return new Bike(this);
        }
    }

    @Override
    public String toString() {
        return "Bike{" +
                "componentA='" + componentA + '\'' +
                ", componentB='" + componentB + '\'' +
                ", componentC='" + componentC + '\'' +
                '}';
    }
}


package com.company.design.builder.simple;

public class Client {
    public static void main(String[] args) {
        Bike bike = new Bike.Builder()
                .setComponentA("componentA")
                .setComponentB("componentB")
                .setComponentC("componentC")
                .build();
        System.out.println(bike.toString());
    }
}

只用了一个类和一个静态内部类,就完成了,很简洁有没有,准确的来说,这里就是把director要做的事情,让客户去写了,对吧?你想怎么构造顺序,你就可以构造出来,其他没有什么区别。

1-4:传统建造者模式的优缺点

搜集了各方面资料总结了下面几点;

  • 优点:
    • 封装了建造的过程,具体的产品是怎么构造的,什么顺序,你并不知道,拿来就用了。
    • 建造者之间相互独立,不受影响。
    • 不需要通过构造方法去实例化对象,从冗长的构造方法中解脱出来,在构造方法中如果你不需要某个参数,你还得把null传递进去,要么就是写多个参数不同的构造方法。
  • 缺点
    • 很明显哈,代码是原来两倍多了,代码变的复杂了。(这可能是最主要的原因)
    • 对每一个产品都得用一个builder来做。(简化后的建造者模式)

1-5:建造者模式使用场景

简言之,当方法执行顺序不同的时候,会得到不同的产品(结果)的时候,就是建造者模式登场的时候,建造者模式关注的是什么?是构造的顺序,顺序!顺序!

1-6:建造者模式和工厂方法模式的区别

同样是创建型,创建产品的,他们区别在哪?

工厂模式只要出来产品就行,什么顺序不顺序它不管,通过工厂模式创建出来的东西都是一样的,而建造者模式,构建顺序不同,出来的东西也不同。 看下面的例子,你就懂了。

在这里插入图片描述

1-7:jdk中的建造者模式-StringBuilder

// 它的产品
char[] value;

@Override
public StringBuilder append(char c) {
    super.append(c);
    return this;
}

// 建造出来的产品
@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

很明显用的是简易的建造者模式,需要加多少char进去,你说了算,也就是我们经常可以调用append,不停地往里面加的原因,原来是用了建造者模式,这样就清晰了!

1-8:参考链接

  • https://stackoverflow.com/questions/757743/what-is-the-difference-between-builder-design-pattern-and-factory-design-pattern
  • https://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/
  • https://www.jianshu.com/p/3d1c9ffb0a28
  • https://segmentfault.com/a/1190000040244002
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河海哥yyds

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值