Builder模式是一種廣泛使用的設(shè)計模式。
將一個復(fù)雜對象的構(gòu)建與它的表示分立,這樣在調(diào)用相同構(gòu)建的過程中可以創(chuàng)建不同的表示
Builder模式分二種,一種是經(jīng)典的Builder模式,第二種是變種Builder模式,而現(xiàn)在Android開發(fā)普遍使用的是第二種的變種Builder模式,下面我們一一來介紹。
---------------------------------我是分割線,不分不舒服------------------------
經(jīng)典的Builder模式
經(jīng)典Buider模式分為四塊:
- Product:被構(gòu)造的復(fù)雜對象。
- Builder:抽象接口。
- BuilderImpl:抽象接口的具體實現(xiàn)。
- Director:接口的構(gòu)造者和使用者。
舉個最簡單的例子。
現(xiàn)在有個廠要生產(chǎn)不同的餅干,有方形的,圓形的等。
我們先建立餅干的類
public class Cookies {
private String shape;
public String getShape(){
return shape;
}
public void setShape(String shape){
this.shape = shape;
}
}
然后我們創(chuàng)建Builder接口
public interface Builder{
public void setShape();
public Cookies getCookies();
}
然后實現(xiàn)Builder接口,比如創(chuàng)建一個會建立方形餅干的SquareCookiesBuilder和一個會建立圓形餅干的RoundCookiesBuilder
public class SquareCookiesBuilder implements Builder{
private Cookies cookies;
@Override
public SquareCookiesBuilder(){
this.cookies = new Cookies();
}
@Override
public void setShape(){
this.cookies.setShape("方形");
}
@Override
public Cookies getCookies(){
return this.cookies;
}
}
public class RoundCookiesBuilder implements Builder{
private Cookies cookies;
@Override
public RoundCookiesBuilder(){
this.cookies = new Cookies();
}
@Override
public void setShape(){
this.cookies.setShape("圓形");
}
@Override
public Cookies getCookies(){
return this.cookies;
}
}
最后創(chuàng)建Director類
public class Director {
private Builder builder;
public Director(Builder builder){
this.builder = builder;
}
public void createCookies(){
this.builder.setShape()
}
public Cookies getCookies(){
return this.builder.getCookies();
}
}
這樣就是
比如獲取方形的餅干
new Director(new SquareCookiesBuilder()).createCookies().getCookies()
比如獲取圓形的餅干。
new Director(new RoundCookiesBuilder()).createCookies().getCookies()
二者的區(qū)別就是對Director傳入不同形狀餅干的Builder的實現(xiàn)類。
而Director的對象調(diào)用的方法都是createCookies()和getCookies()
所以經(jīng)典的Builder模式重點在于抽象出對象創(chuàng)建的步驟,并通過調(diào)用不同的具體實現(xiàn)類從而得到不同的結(jié)果,而變種的Builder模式的目的在于減少對象創(chuàng)建過程中引入的多個重載構(gòu)造函數(shù),可選參數(shù)以及setters過度使用導(dǎo)致的不必要的復(fù)雜性
--------------------------我是變種分割線O(∩_∩)O~----------------------------
變種Builder模式
我們一步步來。比如還是Cookies舉例。就單純的還是形狀。
public class Cookies {
private final String shape;
}
(一般來說,我們盡量將屬性值定義為不可變的??偛荒茱灨啥家呀?jīng)做成方的了。再把它改成圓形吧)
那這時候怎么對這個shape賦值呢。你可能會想到
- 構(gòu)造函數(shù)
因為參數(shù)是final類型了。所以必須在構(gòu)造函數(shù)中進(jìn)行初始化,否則不能編譯通過
public class Cookies {
private final String shape;
pubic class Cookies(String shape){
this.shape = shape;
}
}
這樣看是沒問題。但是如果我們不是餅干,是一個人:Person類。它有name,gender,age三個屬性。但是用戶并不是要每個屬性都要輸入的。這時候就要建立多個構(gòu)造函數(shù)。
public class Person {
private final String name;
private final String gender;
private final String age;
pubic class Person(String name){
this(name,"男","20");
}
pubic class Person(String name,String gender){
this(name,gender,"20")
}
pubic class Person(String name,String gender,String age){
this.name = name;
this.gender = gender;
this.age = age;
}
}
這種構(gòu)造函數(shù)雖然簡單,但是當(dāng)屬性多了的時候。代碼就會變得不易維護(hù),而且構(gòu)造函數(shù)里面的參數(shù)的順序也很容易弄錯。當(dāng)參數(shù)有五個。你還記得第幾個參數(shù)要填年齡?記得第幾個參數(shù)要填姓名?
- getters 和 setters 函數(shù)
public class Cookies {
private String shape;
public void setShape(String shape){
this.shape = shape;
}
public String getShape(){
return this.shape;
}
}
優(yōu)點:你可以建立對象,然后對你想要修改的屬性進(jìn)行修改,比如有二個屬性,你可以只要調(diào)用你想修改的屬性的set方法就可以進(jìn)行修改。
缺點:
1.因為是set方法,所以shape的參數(shù)不在是final修飾了,因為你本身可以多次調(diào)用set方法。這樣Cookies類就變成可變類了。失去了不可變類的好處了。
2.比如剛那個Person類,有三個屬性。當(dāng)你要給它的對象賦值這三個屬性的時候,就要
Person person = new Person();
person.setName("青蛙ing");
person.setAge("20");
person.setGender("男");
失去一種連貫的感覺,而且這還只有三個屬性。要是10個。你這樣一行行的set方法寫十遍??
----------------------我是主角分割線(我是主角?。。?-------------------
還是以上面的Person類為例子。
public class Person {
private final String name;
private final String gender;
private final String age;
private Person(Builder builder) {
name = builder.name;
gender = builder.gender;
age = builder.age;
}
public String getName() {
return name;
}
public String getGender() {
return gender;
}
public String getAge() {
return age;
}
public static final class Builder {
private String name;
private String gender;
private String age;
public Builder() {
}
public Builder name(String val) {
name = val;
return this;
}
public Builder gender(String val) {
gender = val;
return this;
}
public Builder age(String val) {
age = val;
return this;
}
public Person build() {
return new Person(this);
}
}
}
從上述代碼可以看出:
1.Person類的構(gòu)造函數(shù)是私有的。這樣就不能直接實例化這個類
2.Person類是不可變的。里面的屬性都是final的。只能在構(gòu)造函數(shù)中初始化。然后提供了屬性的get函數(shù),可以去獲取值。
3.連貫性,這個Person的創(chuàng)建是:
new Person.Builder().name("青蛙ing").gender("男").age("20").build();
就問你這么寫爽不爽。!!
------------------------------我是插件介紹線------------------------------------
這一段我就不自己截圖了。
就引用別人的插件介紹了。
感謝CSDN的拭心
從他的文章里面拿了插件介紹的圖片和內(nèi)容
http://blog.csdn.net/u011240877/article/details/53248917
變種Builder模式自動化生成
1.下載插件 InnerBuilder:
2.重啟 Andriod Studio;
3.寫好要構(gòu)建的類的變量:
比如:
public class PersonTest {
private final String mName;
private int mAge;
private String mLocation;
}
4.按 Control + Insert (Mac :command + N):
5.在彈出的 Generate 對話框中選擇 Builder:
6.選中要使用 Builder 構(gòu)建的對象,然后勾選使用的配置,點擊OK
public class PersonTest {
private final String mName;
private int mAge;
private String mLocation;
private PersonTest(Builder builder) {
mName = builder.mName;
mAge = builder.mAge;
mLocation = builder.mLocation;
}
public static final class Builder {
private String mName;
private int mAge;
private String mLocation;
public Builder() {
}
public Builder mName(String mName) {
this.mName = mName;
return this;
}
public Builder mAge(int mAge) {
this.mAge = mAge;
return this;
}
public Builder mLocation(String mLocation) {
this.mLocation = mLocation;
return this;
}
public PersonTest build() {
return new PersonTest(this);
}
}
}