使用Builder來構建一個物件

月光邊境發表於2018-01-18

對於一個有著大量可選引數的類來說,我們在構建的時候一般有一下幾種方式:

####一:重疊構造模式: 比如Android中的View

 public class MyView extends View {
        public MyView(Context context) {
            super(context);
        }

        public MyView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);

        }

        public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);

        }
    }
複製程式碼

這種模式我們可以根據具體場景使用不同的構造方法來建立一個MyView物件。這種方式在引數個數較少時可行,但是當如果一個類引數過多並且有相同型別的引數,我們在建立物件的時候必須小心的檢查具體呼叫的那一個構造方法,因為我們很容易顛倒引數的順序,此時編譯器也並不會報錯,(比如在View的構建方法中我把defStyleAttr和defStyleRes兩個方法的順序顛倒)。

####二:JavaBean模式,這應該算是我們最常用的一種形式

  public class User {
        private long uid;
        private String nick;
        private int gender;
        private int age;
        private String email;

        public long getUid() {
            return uid;
        }

        public void setUid(long uid) {
            this.uid = uid;
        }

        public String getNick() {
            return nick;
        }

        public void setNick(String nick) {
            this.nick = nick;
        }

        public int getGender() {
            return gender;
        }

        public void setGender(int gender) {
            this.gender = gender;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }
    }
複製程式碼

建立一個JavaBean物件:

	User user = new User();
    user.setAge(23);
    user.setGender(1);
    user.setNick("superman");
    user.setEmail("abc@xx.com");
    user.setUid(10001);
複製程式碼

這種模式程式碼看上去邏輯很清晰,也解決了多個構造器的不足,但是它自身也有一個缺陷:在涉及到多執行緒的時候,我們在構造物件的過程中物件可能處於不一致的狀態。

####三:Builder構建模式(比如Android中的我們常用的AlertDialog)

 public class Desk {
        private int length;
        private int width;
        private int height;
        private int weight;
        private int color;
        private int price;

        public static class Builder {
            private int length = 0;
            private int width = 0;
            private int height = 0;
            private int weight = 0;
            private int color = 0;
            private int price = 0;

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

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

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

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

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

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

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

        private Desk(Builder builder) {
            length = builder.length;
            width = builder.width;
            height = builder.height;
            weight = builder.weight;
            color = builder.color;
            price = builder.price;
        }
    }
複製程式碼

構建一個物件:

Desk.Builder builder = new Desk.Builder();
    Desk desk = builder.length(2000)

            .width(1600)

            .height(1400)

            .weight(1000)

            .color(Color.BLACK)

            .price(500)

            .build();
複製程式碼

這種方式兼具上面兩種方式的優點並解決了兩種方式各自的缺陷,並且程式碼看上去也很容易閱讀。但是它自身也還是有一些缺陷的,在建立一個物件的時候必須先構建一個他的Builder物件,還是增加了一些開銷。

相關文章