參與者
- Builder
爲創建一個Product對象的各個部件指定抽象接口。 - ConcreteBuilder
實現Builder的接口以構造和裝配該產品的各個部件。
定義並明確它所創建的表示。
提供一個檢索產品的接口 - Director
構造一個使用Builder接口的對象。 - Product
表示被構造的複雜對象。ConcreateBuilder創建該產品的內部表示並定義它的裝配過程。
包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。
使用場景
產品複雜,且它允許使用者不必知道內部構建細節的情況下使用。
注意:現實開發過程中,Director角色經常會被省略。直接使用Builder來進對象的組裝,這個Builder通常爲鏈式調用,它的關鍵點是每個方法都返回自身 - return this,這使得set方法可以鏈式調用,代碼如下:
Test test = new Test.Builder().setA("A").setB("B").create();
Code
/** "Product" */
class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";
public void setDough (String dough) { this.dough = dough; }
public void setSauce (String sauce) { this.sauce = sauce; }
public void setTopping (String topping) { this.topping = topping; }
}
''/** "Abstract Builder" */''
abstract class PizzaBuilder {
protected Pizza pizza;
public Pizza getPizza() { return pizza; }
public void createNewPizzaProduct() { pizza = new Pizza(); }
public abstract void buildDough();
public abstract void buildSauce();
public abstract void buildTopping();
}
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("cross"); }
public void buildSauce() { pizza.setSauce("mild"); }
public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("pan baked"); }
public void buildSauce() { pizza.setSauce("hot"); }
public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}
''/** "Director" */''
class Waiter {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder (PizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }
public void constructPizza() {
pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
}
}
調用
/** A customer ordering a pizza. */
class BuilderExample {
public static void main(String[] args) {
Waiter waiter = new Waiter();
PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();
PizzaBuilder spicy_pizzabuilder = new SpicyPizzaBuilder();
waiter.setPizzaBuilder ( hawaiian_pizzabuilder );
waiter.constructPizza();
Pizza pizza = waiter.getPizza();
}
}
實際場景舉一例
okhttputils請求Get分析
String url = "http://www.csdn.net/";
OkHttpUtils
.get()
.url(url)
.build()
.execute(new MyStringCallback());
首先看到這裏有個build(),估計就是建造模式了,摸進去一看,沒有錯。
.get()
進去一看,果然不假
public static GetBuilder get()
{
return new GetBuilder();
}
public class GetBuilder extends OkHttpRequestBuilder
{
@Override
public RequestCall build()
{
if (params != null)
{
url = appendParams(url, params);
}
return new GetRequest(url, tag, params, headers).build();
}
// ...
@Override
public GetBuilder url(String url)
{
this.url = url;
return this;
}
// ...
}
這裏設定了url,且看到已經看到了build()方法,基本和最初的判定一致,是Builder模式,但這跟Okhttp用法還是有差距,繼續跟進,發現最初.get()
的GetBuilder直接將設置的數據全部扔進OkHttpRequest了 - 這、、、
public class GetRequest extends OkHttpRequest
{
public GetRequest(String url, Object tag, Map<String, String> params, Map<String, String> headers)
{
super(url, tag, params, headers);
}
// ...
@Override
protected Request buildRequest(Request.Builder builder, RequestBody requestBody)
{
return builder.get().build();
}
尼瑪,坑啊,build()沒有?繼續
public abstract class OkHttpRequest
{
protected String url;
protected Object tag;
protected Map<String, String> params;
protected Map<String, String> headers;
protected Request.Builder builder = new Request.Builder();
protected OkHttpRequest(String url, Object tag,
Map<String, String> params, Map<String, String> headers)
{
this.url = url;
this.tag = tag;
this.params = params;
this.headers = headers;
if (url == null)
{
Exceptions.illegalArgument("url can not be null.");
}
}
// ...
protected abstract Request buildRequest(Request.Builder builder, RequestBody requestBody);
public RequestCall build()
{
return new RequestCall(this);
}
public Request generateRequest(Callback callback)
{
RequestBody requestBody = wrapRequestBody(buildRequestBody(), callback);
prepareBuilder();
return buildRequest(builder, requestBody);
}
private void prepareBuilder()
{
builder.url(url).tag(tag);
appendHeaders();
}
// ...
}
終於看到我辛苦設置的參數都在這裏了,返回了RequestCall,也看到眼熟的Requset.Builder,但目前還是沒有看到誰調用了它,看來還得繼續深入RequestCall
public class RequestCall
{
private OkHttpRequest okHttpRequest;
private Request request;
private Call call;
// ...
private OkHttpClient clone;
public RequestCall(OkHttpRequest request)
{
this.okHttpRequest = request;
}
// ...
public Call generateCall(Callback callback)
{
request = generateRequest(callback);
if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0)
{
readTimeOut = readTimeOut > 0 ? readTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;
writeTimeOut = writeTimeOut > 0 ? writeTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;
connTimeOut = connTimeOut > 0 ? connTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;
clone = OkHttpUtils.getInstance().getOkHttpClient().newBuilder()
.readTimeout(readTimeOut, TimeUnit.MILLISECONDS)
.writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)
.connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)
.build();
call = clone.newCall(request);
} else
{
call = OkHttpUtils.getInstance().getOkHttpClient().newCall(request);
}
return call;
}
private Request generateRequest(Callback callback)
{
return okHttpRequest.generateRequest(callback);
}
public void execute(Callback callback)
{
generateCall(callback);
if (callback != null)
{
callback.onBefore(request);
}
OkHttpUtils.getInstance().execute(this, callback);
}
// ...
public Response execute() throws IOException
{
generateCall(null);
return call.execute();
}
// ...
}
在這裏可以看到Client,request,call了,OkHttpUtils.getInstance().getOkHttpClient()
、request = generateRequest(callback)
、generateCall
,且最後還執行了execute
- call.execute()
總結一下這個開源
OkHttpUtils.get().url(url).build()
得到了RequestCall,Builder模式呈現- 化繁爲簡,網絡請求不需要自己再封裝就能夠方便的使用
- 設置下url,就有了OkHttp的Client,request,call和一系繁鎖設置,直接調用execute()
- execute(Callback callback)方法會回調到OkHttpUtils,用主線程Handler更新請求
- 將OkHttpClient放進了OkHttpUtils;將Request轉變成GetRequest;將Request.Builder替換成GetBuilder;將Call替換成RequestCall