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

简介: 首先,我们来定义一个Product类:接下来,我们定义抽象的Builder类:然后,是具体的Builder实现类:

640.png640.png640.png640.png640.png640.png640.png640.png640.png640.png

 

 

————————————

640.png640.png640.png640.png640.png640.png640.png640.png640.png640.png

 

 

首先,我们来定义一个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();

 

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




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

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

640.png640.png640.png

 


// 默认采用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);
  }
}

640.png640.png

/**将指定的字符串追加到此字符序列*/
@Override
public StringBuilder append(CharSequence s) {
    super.append(s);// 实现过程略
    return this;
}
/**将此字符序列用其反转形式取代*/
@Override
public 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: 故由自为若只要主义真

 

640.png640.png640.png640.png640.png640.png640.png640.png


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

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

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

 

 640.png640.png640.png640.png

 

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

640.png640.png640.png640.png

 

 

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




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);

640.png640.png640.png640.png640.png 

相关文章
|
设计模式 uml
23种设计模式漫画版系列—生成器模式(一)
23种设计模式漫画版系列—生成器模式
99 0
|
设计模式 Java 领域建模
23种设计模式漫画版系列—生成器模式(二)
23种设计模式漫画版系列—生成器模式(二)
74 0
|
设计模式 Go iOS开发
23种设计模式漫画版系列—抽象工厂
23种设计模式漫画版系列—抽象工厂
58 0
|
设计模式 Java uml
全面通透深入剖析工厂方法模式
工厂方法模式主要适用于以下应用场景。 (1)创建对象需要大量重复的代码。 (2)客户端(应用层)不依赖产品类实例如何被创建、实现等细节。 (3)一个类通过其子类来指定创建哪个对象。
112 0
建造者模式——画胖小人和瘦小人
建造者模式——画胖小人和瘦小人
GOF之建造者模式(创建型模式)附图详解 ✨ 每日积累
GOF之建造者模式(创建型模式)附图详解 ✨ 每日积累
GOF之建造者模式(创建型模式)附图详解 ✨ 每日积累
|
XML 设计模式 Java
漫画:什么是 “抽象工厂模式” ?
抽象工厂模式: 抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。
188 0
漫画:什么是 “抽象工厂模式” ?
|
存储 设计模式 Java
漫画:什么是 “原型模式” ?
在Java语言中,Object类实现了Cloneable接口,一个对象可以通过调用Clone()方法生成对象,这就是原型模式的典型应用。 但需要注意的是,clone()方法并不是Cloneable接口里的,而是Object类里的,Cloneable是一个标识接口,标识这个类的对象是可被拷贝的,如果没有实现Cloneable接口,却调用了clone()方法,就会报错。
206 0
漫画:什么是 “原型模式” ?
|
设计模式
漫画:设计模式之 “工厂模式”
假设我们的业务代码当中,有一个被广泛引用的“口罩类”,这个类实例需要在许多地方被创建和初始化,而初始化的代码也比较复杂。
163 0
漫画:设计模式之 “工厂模式”
漫画:什么是 “代理模式” ?
在上面的代码中,代理类和业务类继承了相同的接口,并且重写了添加/删除学生的方法。 在重写的方法中,我们不仅可以调用业务类的原有方法,并且在调用的前后可以进行额外的处理,比如加上日志、事务等等。 这样一来,在客户端当中,我们只要创建了代理类,就可以像使用业务类一样使用它,非常方便:
149 0
漫画:什么是 “代理模式” ?