當(dāng)前位置:首頁 > 公眾號精選 > 程序員小灰
[導(dǎo)讀]—————?第二天?—————————————————?首先,我們來定義一個Product類:public?class?Product?{????ArrayList?parts?=?new?ArrayList();????public?void?add(String?part)?...



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



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


?



首先,我們來定義一個Product類:


public?class?Product?{
????ArrayList?parts?=?new?ArrayList();

????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實現(xiàn)類:


public?class?ConcreteBuilder?extends?Builder?{
????private?Product?product?=?new?Product();
????public?Product?getResult()?{
????????return?product;
????}
????@Override
????public?void?buildPartA()?{
????????product.add("構(gòu)建產(chǎn)品的上半部分");
????}

????@Override
????public?void?buildPartB()?{
????????product.add("構(gòu)建產(chǎn)品的下半部");
????}
}

在Builder類之外,則是Director類來控制Builder的生產(chǎn)過程:


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

我們來看一下運(yùn)行的結(jié)果


[構(gòu)建產(chǎn)品的上半部分,?構(gòu)建產(chǎn)品的下半部分]




//?默認(rèn)采用Builder進(jìn)行建造
public?OkHttpClient()?{
??this(new?Builder());
}

//?由builder配置分發(fā)器、代理、協(xié)議以及自定義攔截器等
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()?{
//?分發(fā)器、協(xié)議、代理的默認(rèn)參數(shù)
????dispatcher?=?new?Dispatcher();
????protocols?=?DEFAULT_PROTOCOLS;
????proxySelector?=?ProxySelector.getDefault();
????if?(proxySelector?==?null)?{
??????proxySelector?=?new?NullProxySelector();
????}
??}

??Builder(OkHttpClient?okHttpClient)?{
????//?反向配置分發(fā)器、代理、協(xié)議
????this.dispatcher?=?okHttpClient.dispatcher;?
????this.proxy?=?okHttpClient.proxy;?
????this.protocols?=?okHttpClient.protocols;
//?新增所有自定義攔截器和自定義網(wǎng)絡(luò)攔截器
????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);//?實現(xiàn)過程略
????return?this;
}
/**將此字符序列用其反轉(zhuǎn)形式取代*/
@Override
public?StringBuilder?reverse()?{
????super.reverse();//?實現(xiàn)過程略
????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);

測試結(jié)果如下:


System.out:?真義主要只故由自為若
System.out:?故由自為若只要主義真





建造者模式與簡單工程模式的區(qū)別,在于建造者模式多出一個Builder類,使得創(chuàng)建對象的靈活性大大增加,適用于如下場景:


(1)創(chuàng)建一個對象,多個同樣的方法的調(diào)用順序不同,產(chǎn)生的結(jié)果不同

(2)創(chuàng)建一個對象,特別復(fù)雜,參數(shù)多,而且很多參數(shù)都有默認(rèn)值

?




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



短短一行代碼,背后有什么樣的機(jī)制呢?


Java的編譯原理,是將Hello.java編譯成能被VM理解的Hello.class,然后再轉(zhuǎn)化為能被不同硬件設(shè)備理解的bytecode進(jìn)而執(zhí)行的。


著名的字節(jié)碼增強(qiáng)框架ASM,就是在Hello.java編譯成Hello.class時可以讀取并分析類信息、改變類行為、增強(qiáng)類功能甚至生成新的類的bytecode分析和操作框架。


我們來看一下相關(guān)的代碼,代碼當(dāng)中的mv,來自ASM框架的MethodVisitor接口。


//?訪問System類的類型為PrintSystem類型的靜態(tài)變量out
mv.visitFieldInsn(Opcodes.GETSTATIC,?"java/lang/System",?"out",?"Ljava/io/PrintStream;");
//?訪問常量池中的數(shù)據(jù)"Hello?World"
mv.visitLdcInsn("Hello?World");
//?調(diào)用PrintStream類的println()方法并把剛才獲取到的對象當(dāng)做String類型的參數(shù)傳入
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,?"java/io/PrintStream",?"println",?"(Ljava/lang/String;)V",?false);


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉