作者:东风玖哥
来源: 程序员小灰
————— 第二天 —————
————————————
首先,我们来定义一个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;}@Overridepublic void buildPartA() {product.add("构建产品的上半部分");}@Overridepublic 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();
System.out.println(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);}
}
/**将指定的字符串追加到此字符序列*/
@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: 故由自为若只要主义真
建造者模式与简单工程模式的区别,在于建造者模式多出一个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);
往期推荐
实现工具自由!开源的工具桌面箱
TCP泄露了操作系统信息…
在部队敲代码是一种什么样的体验?
漫画:什么是HTTPS协议?
点分享
点收藏
点点赞
点在看