您的位置:首页 > 理论基础 > 计算机网络

构造模式-OkHttp Request的构建

2018-01-23 16:23 211 查看
Builder模式常用于构建复杂对象,经常使用Builder模式来代替多参数的构造函数,我们常常需要编写这样的实现类,这个类拥有多个构造函数:

public class User {
private int userId;
private String userName;
private int age;
private boolean isMale;

public User(int userId) {
this(userId, null, 0, true);
}

public User(int userId, String userName) {
this(userId, userName, 0, true);
}

public User(int userId, String userName, int age) {
this(userId, userName, age, true);
}

public User(int userId, String userName, int age, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.age = age;
this.isMale = isMale;
}

}


    这样一系列的构造函数主要目的就是给客户提供更多的调用选择,以处理不同的构造请求,类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作,而且如果属性过多的话会让构造函数十分臃肿,使用Builder模式可以通过一个代理来完成对象的构建过程。将上面的多个构造函数改成builder模式如下:

public class User {
private final int userId;
private final String userName;
private final int age;
private final boolean isMale;

public int getUserId() {
return userId;
}

public String getUserName() {
return userName;
}

public int getAge() {
return age;
}

public boolean isMale() {
return isMale;
}

public static class Builder {
private int userId;
private String userName;
private int age;
private boolean isMale;
//必传的参数在构造方法中设置
public Builder(int userId) {
this.userId = userId;
}

public Builder userName(String userName) {
this.userName = userName;
return this;
}

public Builder age(int age) {
this.age = age;
return this;
}

public Builder isMale(boolean isMale) {
this.isMale = isMale;
return this;
}

public User build() {
return new User(this);
}

}

private User(Builder builder) {
userId = builder.userId;
userName = builder.userName;
age = builder.age;
isMale = builder.isMale;
}

}
使用:
User user = new Builder(111).userName("zhangsan").age(26).isMale(true).build();

Builder是User的静态内部类,并且Builder中的属性和User中的属性一致,User所有的属性值设置都在Builder中,User中只有获取属性的方法。
OkHttp中的Request的构造也是采用的builder模式,如下:

public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final RequestBody body;
final Object tag;

Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}

public HttpUrl url() {
return url;
}

public String method() {
return method;
}

public Headers headers() {
return headers;
}

public String header(String name) {
return headers.get(name);
}

public List<String> headers(String name) {
return headers.values(name);
}

public RequestBody body() {
return body;
}

public Object tag() {
return tag;
}

public Builder newBuilder() {
return new Builder(this);
}

public CacheControl cacheControl() {
CacheControl result = cacheControl;
return result != null ? result : (cacheControl = CacheControl.parse(headers));
}

public boolean isHttps() {
return url.isHttps();
}

public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body;
Object tag;

public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}

Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tag = request.tag;
this.headers = request.headers.newBuilder();
}

public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}

public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");

// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}

HttpUrl parsed = HttpUrl.parse(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}

public Builder url(URL url) {
if (url == null) throw new NullPointerException("url == null");
HttpUrl parsed = HttpUrl.get(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}

public Builder header(String name, String value) {
headers.set(name, value);
return this;
}

public Builder addHeader(String name, String value) {
headers.add(name, value);
return this;
}

public Builder removeHeader(String name) {
headers.removeAll(name);
return this;
}

public Builder headers(Headers headers) {
this.headers = headers.newBuilder();
return this;
}

public Builder cacheControl(CacheControl cacheControl) {
String value = cacheControl.toString();
if (value.isEmpty()) return removeHeader("Cache-Control");
return header("Cache-Control", value);
}

public Builder get() {
return method("GET", null);
}

public Builder head() {
return method("HEAD", null);
}

public Builder post(RequestBody body) {
return method("POST", body);
}

public Builder delete(RequestBody body) {
return method("DELETE", body);
}

public Builder delete() {
return delete(Util.EMPTY_REQUEST);
}

public Builder put(RequestBody body) {
return method("PUT", body);
}

public Builder patch(RequestBody body) {
return method("PATCH", body);
}

public Builder method(String method, RequestBody body) {
if (method == null) throw new NullPointerException("method == null");
if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
if (body != null && !HttpMethod.permitsRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must not have a request body.");
}
if (body == null && HttpMethod.requiresRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must have a request body.");
}
this.method = method;
this.body = body;
return this;
}

public Builder tag(Object tag) {
this.tag = tag;
return this;
}

/*
* Request 对象创建器,想得到一个Request 对象必须使用build 方法,
* 在方法中增加对Builder参数的验证,并以异常的形式告诉给开发人员。
*/
public Request build() {
/**
* 比如下面判断如果 url 是null的话就会抛出异常
*/
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
}
}


使用Builder构造一个Request对象:

Request request = new Request.Builder()
.url("http://www.youtube.com")
.addHeader("header","header")
.put("RequestBody")
.build();


    Builder模式创建的对象,在调用build()方法之前是不会创建Request对象的,所有的属性设置都必须在build()方法之前,而且创建了Request对象后就不可以更改其属性了,这就保证了对象状态的唯一性,而且代码的可读性也提高了;如果有些参数是必填的,可以加到Builder 的构造函数中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息