漫画:什么是 “建造者模式” ?

本文通过实例详细解析了建造者模式的实现,包括Product、Builder、ConcreteBuilder和Director类的角色与职责。同时,展示了如何在OkHttp库中使用建造者模式。此外,还探讨了建造者模式与简单工厂模式的区别,以及适用场景。最后,提到了Java编译原理的简要介绍。

作者 | 东风玖哥,小灰

来源 | 程序员小灰(ID:chengxuyuanxiaohui)

—————  第二天  —————


———————————

首先,我们来定义一个Product类:

public class Product {    ArrayList<String> parts = new ArrayList<String>();
    public void add(String part) {        parts.add(part);    }
    public void show() {        System.out.println(parts);    }}

接下来,我们定义抽象的Builder类:

public abstract class Builder {    public abstract void buildPartA();    public abstract void buildPartB();    public abstract Product getResult() ;}

然后,是具体的Builder实现类:

public class ConcreteBuilder extends Builder {
    private Product product = new Product();
    public Product getResult() {
        return product;
    }
    @Override
    public void buildPartA() {
        product.add("构建产品的上半部分");
    }


    @Override
    public void buildPartB() {
        product.add("构建产品的下半部分");
    }
}


在Builder类之外,则是Director类来控制Builder的生产过程:

public class Director {    private Builder builder;
    public Director(Builder builder) {        this.builder = builder;    }
    public void construct() {        builder.buildPartA();        builder.buildPartB();    }}

最后,是客户端的测试代码:

Builder builder = new ConcreteBuilder();Director director = new Director(builder);director.construct();Product product = builder.getResult();product.show();

我们来看一下运行的结果:

[构建产品的上半部分, 构建产品的下半部分]

// 默认采用Builder进行建造public OkHttpClient() {  this(new Builder());}
// 由builder配置分发器、代理、协议以及自定义拦截器等OkHttpClient(Builder builder) {  this.dispatcher = builder.dispatcher;  this.proxy = builder.proxy;  this.protocols = builder.protocols;  /** 省略大段代码 */  boolean isTLS = false;  for (ConnectionSpec spec : connectionSpecs) {    isTLS = isTLS || spec.isTls();  }  /** 省略大段代码. */  if (interceptors.contains(null)) {    throw new IllegalStateException("Null interceptor: " + interceptors);  }  if (networkInterceptors.contains(null)) {    throw new IllegalStateException("Null network interceptor: " + networkInterceptors);  }}public static final class Builder {
  public Builder() {// 分发器、协议、代理的默认参数    dispatcher = new Dispatcher();    protocols = DEFAULT_PROTOCOLS;    proxySelector = ProxySelector.getDefault();    if (proxySelector == null) {      proxySelector = new NullProxySelector();    }  }
  Builder(OkHttpClient okHttpClient) {    // 反向配置分发器、代理、协议    this.dispatcher = okHttpClient.dispatcher;     this.proxy = okHttpClient.proxy;     this.protocols = okHttpClient.protocols;// 新增所有自定义拦截器和自定义网络拦截器    this.interceptors.addAll(okHttpClient.interceptors);    this.networkInterceptors.addAll(okHttpClient.networkInterceptors);  }
  // 配置代理  public Builder proxy(@Nullable Proxy proxy) {    this.proxy = proxy;    return this;  }  // 向拦截器链中增加自定义拦截器  public Builder addInterceptor(Interceptor interceptor) {    if (interceptor == null) throw new IllegalArgumentException("interceptor == null");    interceptors.add(interceptor);    return this;  }  // 最后是build()方法,生成OkHttpClient对象  public OkHttpClient build() {    return new OkHttpClient(this);  }}

/**将指定的字符串追加到此字符序列*/@Overridepublic StringBuilder append(CharSequence s) {    super.append(s);// 实现过程略    return this;}/**将此字符序列用其反转形式取代*/@Overridepublic StringBuilder reverse() {    super.reverse();// 实现过程略    return this;}

下面让我们来编写一下测试代码:

StringBuilder sb = new StringBuilder("若为自由故");sb.append("只要主义真");sb.reverse();System.out.println(sb);StringBuilder sb1 = new StringBuilder("若为自由故");sb1.reverse();sb1.append("只要主义真");System.out.println(sb1);

测试结果如下:

System.out: 真义主要只故由自为若System.out: 故由自为若只要主义真

建造者模式与简单工程模式的区别,在于建造者模式多出一个Builder类,使得创建对象的灵活性大大增加,适用于如下场景:

(1)创建一个对象,多个同样的方法的调用顺序不同,产生的结果不同

(2)创建一个对象,特别复杂,参数多,而且很多参数都有默认值


System.out.println("Hello World");

短短一行代码,背后有什么样的机制呢?

Java的编译原理,是将Hello.java编译成能被VM理解的Hello.class,然后再转化为能被不同硬件设备理解的bytecode进而执行的。

著名的字节码增强框架ASM,就是在Hello.java编译成Hello.class时可以读取并分析类信息、改变类行为、增强类功能甚至生成新的类的bytecode分析和操作框架。

我们来看一下相关的代码,代码当中的mv,来自ASM框架的MethodVisitor接口。

// 访问System类的类型为PrintSystem类型的静态变量out
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
// 访问常量池中的数据"Hello World"
mv.visitLdcInsn("Hello World");
// 调用PrintStream类的println()方法并把刚才获取到的对象当做String类型的参数传入
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);

☞让汽车软件进入 iPhone 时代!
☞国内首家!携程每周两天可在家“躺平”,76% 的员工主动报名
☞苹果新功能惹众怒,4000 多家组织和个人签署公开信,敦促苹果放弃“儿童安全”功能
☞Windows 11 再惹“众怒”!网友:微软就是逼我去买新电脑!
☞程序员因开发速度太慢而遭公司起诉,索赔金额高达90万!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值