1. 程式人生 > >Android之Builder建造者模式

Android之Builder建造者模式

在我們日常研發中,建造者模式是使用的很多的一種模式。其實很多時候我們在不知不覺中就使用了別人設計的建造者模式而從中受益。比如Gson、okHttp、Retrift。如下程式碼:

Gson gson = new GsonBuilder()
          .registerTypeAdapter(String.class,new StringAdapter())
          .registerTypeAdapter(Integer.class,new IntegerAdapter())
          .registerTypeAdapter(int.class,new IntegerAdapter())
          .create();

先通過Builder然後在設定一些想要設定的引數,最後通過create()得到需要的物件。比起我們通常使用的建構函式、setter等的設定其好處是鏈式呼叫,欲設定的引數清晰,返回物件時機明確。

那我們也可以參考這種設計來設計我們自己類為建造者模式進行建造。

設計一個Student類如下:

public class Student {
    private final String name;
    private final String age;
    private final String phone;
    private final String address;
    private Student(Builder builder){
        this.name = builder.name;
        this.address = builder.address;
        this.age = builder.age;
        this.phone = builder.phone;
    }

    public String getName() {
        return name;
    }

    public static class Builder{
        private final String name;
        private final String age;
        private String phone;
        private String address;
        public Builder(String name,String age){
            this.name = name;
            this.age = age;
        }
        public Builder setPhone(String phone){
            this.phone = phone;
            return this;
        }
        public Builder setAddress(String address){
            this.address = address;
            return this;
        }
        public Student build(){
            Student student = new Student(this);
            if(student.getName().equals("calm")){
                throw new IllegalStateException("calm是非法使用者");
            }
            return student;
        }
    }

    @Override
    public String toString() {
        return "name = "+name+" age = "+age+" phone = "+phone+" address = "+address;
    }
}

核心思想在內部的靜態Bulider類,我們將建造的時候必須的引數放在Builder的建構函式中,非必須引數通過鏈式呼叫進行設定。最後通過build()方法返回Student物件。build()方法呼叫Student的私有建構函式,這個建構函式接收Builder作為引數。需要注意的是,如果要對返回物件的引數做合法化驗證的話,一定要先構建物件在進行驗證。因為在構建的過程中,是非執行緒安全的,意味著如果沒構建之前去檢測的話,可能會被別的執行緒更改掉檢測的引數而失去了檢測的意義。

最後附上呼叫的程式碼:

Student student = new Student.Builder("Calm","33")
                .setAddress("China")
                .setPhone("19999999999")
                .build();

僅以此記錄建造者模式的使用方式。