經(jīng)典Builder/變種Builder模式及自動化生成代碼插件

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);
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容