参与者
- 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