1. 程式人生 > >java設計模式——Builder模式

java設計模式——Builder模式

Builder模式既構建者模式,可以一步一步地建立一個複雜的物件。記住是複雜的物件,簡單的在使用構建者就冗餘了。很多的開源專案中也都用到了Builder模式,比如Rtrofit , Glide ,Picasso RxJava 等等,安卓系統中用到的也很多,最典型的就是我的的AertDialog。他們的很大的一個特點就是鏈式呼叫。使我們的程式碼寫起來既簡單又爽快。而鏈式呼叫的關鍵就是每個setter方法都返回自身。

下面舉個簡單的例子
有一個物件Person

public class Person {
    private String name;
    private String sex;
    private
double height; private String address; private String phone; private String email; public Person(String name, String sex, double height, String address, String phone, String email) { this.name = name; this.sex = sex; this.height = height; this.address = address; this
.phone = phone; this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public
double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

正常我們建立這個Person物件是

Person person = new Person("大海","男",175,"北京","18813137878","[email protected]");

上面的方法可以構建出Person物件,但是缺點也很明顯,當Person中的引數有很多的時候,我們在構建的時候,根本不知道下面的引數是哪個,還得去類裡面看一下構造引數,在返回來填寫。
另外當我們的Person物件有各種各樣的構造實現,每種構造需要的引數都不一樣,那我們的實體類中就需要寫各種的引數的構造方法,當我們構造物件的時候更加不容易知道我們需要填寫的引數是神馬。
當然我們也可以先構造沒有引數的物件。在一個一個set引數,這樣也很麻煩哦,寫一堆person.set()……

然後看一下builder模式的構建方式

public class Person {
    private String name;
    private String sex;
    private double height;
    private String address;
    private String phone;
    private String email;

   public static class Builder{
       Person mPerson;
       public Builder() {
        mPerson = new Person();
       }
       public  Builder name(String name){
           mPerson.name = name;
           return this;
       }
       public  Builder sex(String sex){
           mPerson.sex = sex;
           return this;
       }
       public  Builder height(double height){
           mPerson.height = height;
           return this;
       }
       public  Builder address(String address){
           mPerson.address = address;
           return this;
       }
       public  Builder phone(String phone){
           mPerson.phone = phone;
           return this;
       }
       public  Builder email(String email){
           mPerson.email = email;
           return this;
       }
       public Person build(){
           return mPerson;
       }
   }
}

構建上面的Person類我們就可以這樣:

Person person = new Person.Builder()
            .name("dahai")
            .sex("man")
            .address("beijing")
            .height(175)
            .phone("18813137878")
            .email("[email protected]")
            .build();

這樣看起來非常清晰,而且我們可以想要幾個引數就新增幾個引數很方便。比直接set引數簡單很多,比使用構造器靈活很多。所以說builder模式是用來一步一步構建複雜的物件的。

下面來了解下AertDialog構建者模式

正常開發中使用AertDialog 一般都是如下;

 new AlertDialog.Builder(this)
                .setIcon(ContextCompat.getDrawable(this,R.mipmap.ic_launcher))
                .setTitle("彈窗標題")
                .setMessage("彈窗內容")
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .create()
                .show();

首先從類名(AlertDialog.Builder)就可以看出這是一個Builder模式。通過Builder物件來構建dialog的各個部分,我們可以根據自己的需要來新增部件,如上面的setTitle , setMessage等。
AlertDialog中的部分程式碼:

public class AlertDialog extends AppCompatDialog implements DialogInterface {

    final AlertController mAlert;

    static final int LAYOUT_HINT_NONE = 0;
    static final int LAYOUT_HINT_SIDE = 1;

    protected AlertDialog(@NonNull Context context) {
        this(context, 0);
    }


    protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
        super(context, resolveDialogTheme(context, themeResId));
        mAlert = new AlertController(getContext(), this, getWindow());
    }

    protected AlertDialog(@NonNull Context context, boolean cancelable,
            @Nullable OnCancelListener cancelListener) {
        this(context, 0);
        setCancelable(cancelable);
        setOnCancelListener(cancelListener);
    }

    public Button getButton(int whichButton) {
        return mAlert.getButton(whichButton);
    }


    public ListView getListView() {
        return mAlert.getListView();
    }

    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        mAlert.setTitle(title);
    }


    public void setCustomTitle(View customTitleView) {
        mAlert.setCustomTitle(customTitleView);
    }


    public void setMessage(CharSequence message) {
        mAlert.setMessage(message);
    }


    public void setView(View view) {
        mAlert.setView(view);
    }  
...... 省略各種set方法......

可以看到 AlertDialog中的set方法設定的引數 最終都儲存在成員變數AlertController中。

Builder 中的程式碼

public static class Builder {
        private final AlertController.AlertParams P;
        private final int mTheme;


        public Builder(@NonNull Context context) {
            this(context, resolveDialogTheme(context, 0));
        }


        public Builder(@NonNull Context context, @StyleRes int themeResId) {
            P = new AlertController.AlertParams(new ContextThemeWrapper(
                    context, resolveDialogTheme(context, themeResId)));
            mTheme = themeResId;
        }


        @NonNull
        public Context getContext() {
            return P.mContext;
        }


        public Builder setTitle(@StringRes int titleId) {
            P.mTitle = P.mContext.getText(titleId);
            return this;
        }


        public Builder setTitle(CharSequence title) {
            P.mTitle = title;
            return this;
        }


        public Builder setCustomTitle(View customTitleView) {
            P.mCustomTitleView = customTitleView;
            return this;
        }


        public Builder setMessage(@StringRes int messageId) {
            P.mMessage = P.mContext.getText(messageId);
            return this;
        }


        public Builder setMessage(CharSequence message) {
            P.mMessage = message;
            return this;
        }


...... 中間省略一堆set ......

        public AlertDialog create() {
            // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
            // so we always have to re-set the theme
            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
            P.apply(dialog.mAlert);
            dialog.setCancelable(P.mCancelable);
            if (P.mCancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
            dialog.setOnCancelListener(P.mOnCancelListener);
            dialog.setOnDismissListener(P.mOnDismissListener);
            if (P.mOnKeyListener != null) {
                dialog.setOnKeyListener(P.mOnKeyListener);
            }
            return dialog;
        }


        public AlertDialog show() {
            final AlertDialog dialog = create();
            dialog.show();
            return dialog;
        }
    }

可以看到 Builder中有一個成員變數AlertController.AlertParams。我的所set的值都儲存AlertController.AlertParams中。AlertController.AlertParams包含了與AlertDialog 檢視中對應的成員變數,在呼叫Builder中的create()的時候,會建立AlertDialog 並通過P.apply(dialog.mAlert)將AlertController.AlertParams中的引數儲存在AlertDialog的成員變數AlertController中,然後返回dialog。

標準的builder模式還有一層Director類來封裝Builder,但是一般真實的開發中一邊都省略Director,直接鏈式的呼叫會更加清晰簡單。

平時的工作中,我們自己寫一些工具類的時候,都可以使用builder模式,來使我們的工具類更加方便使用。

相關推薦

java中的設計模式-Builder模式

Builder 模式的目的? 抽離複雜物件的建構函式,讓我們可以通過多種方法的排列組合構建複雜的物件。如果構造器引數過多,可以考慮 builder 模式 這樣說也有點抽象,舉個例子吧。 舉個例子 比如 非常熱門的訊息佇列RabbitMQ 的 AMQP.BasicProperties 因為它的屬性比較多

Java設計模式--Builder模式

Java設計模式–Builder模式 標籤(空格分隔): 設計模式 本文是遇到實際問題想辦法解決,並沒有詳細解釋理論,博主水平有限. 1.問題提出 問題的提出來源於實際程式碼中遇到的問題,下面講述問題. 公司做一個WebService服務,因為

java設計模式——Builder模式

Builder模式既構建者模式,可以一步一步地建立一個複雜的物件。記住是複雜的物件,簡單的在使用構建者就冗餘了。很多的開源專案中也都用到了Builder模式,比如Rtrofit , Glide ,Picasso RxJava 等等,安卓系統中用到的也很多,最典型

Java 設計---Proxy 代理模式

何謂代理模式        代理模式是指客戶端不直接呼叫服務物件,而是通過代理服務去呼叫物件。 應用場景          1.當需要為一個物件在不同的地址空間提供區域性的代表時;此時的代理模式

設計模式-builder模式(以微信訊息的路由處理為例)

今天要講一個簡單的模式–builder模式。 你可能會覺得,builder模式有什麼好講的?本來我也這樣覺得,但當我有幸拜讀某位大神通過builder模式寫了一個開發工具包的初始化操作,嗯程式碼的樣子很叼 這位大神是誰呢? 就是這位仁兄啦,是碼雲上一個很火的微信開發工具包的貢獻者之一。

設計模式 --- Builder模式

1.定義 將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。   2.使用場景 1.相同的方法,不同的執行順序,產生不同的結果。 2.多個部分都可以裝配到一個物件中,但產生的結果又不相同。 3.產品類非常複雜,或者產品類的呼叫順序不同產生了不

設計模式-Builder模式(一)

一,builder模式簡介    定義 將一個複雜物件的構建與他的表示分離,使得同樣的構建過程可以建立不同的表示。      使用場景         (1)相同的方法,不同的執行順序,產生不同的事件結果         (2)多個部件或零件,都可以裝配到一個物件,但

設計模式-builder模式(以微信訊息的路由為例講解)

今天要講一個簡單的模式–builder模式。 你可能會覺得,builder模式有什麼好講的?本來我也這樣覺得,但當我有幸拜讀某位大神通過builder模式寫了一個開發工具包的初始化操作,嗯程式碼的樣子很叼 這位大神是誰呢? 就是這位仁兄啦,是碼雲上一個很火的微

Android開發中無處不在的設計模式——Builder模式

上一篇文章介紹了單例模式,這一篇繼續介紹一個常見的模式——Builder模式。 那麼什麼是Builder模式呢。你通過搜尋,會發現大部分網上的定義都是 將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示 但是看完這個定義,並沒

Android中設計模式-Builder模式

遇到多個構造器引數時要考慮使用構建器 引入:當我們建立物件傳遞引數的時候,往往通過構造方法來傳,如下程式碼: public class Person { private String name; private String id;

構建者模式——Builder模式

只有你學會把自己已有的成績都歸零,才能騰出空間去接納更多的新東西,如此才能使自己不斷的超越自己。 現在我們將要學習一種新的模式——構建者模式,這種模式大家想必也遇到過, 比如Android中的AlertDialog.build()這樣就會創建出一個Alert

java設計模式】【創建模式Creational Pattern】建造模式Builder Pattern

part main ons rod over res {} retrieve [] 1 package com.tn.pattern; 2 3 public class Client { 4 public static void main(String[

java 建造者Builder設計模式解析

Builder模式介紹         1.使用者使用簡單,不需要知道內部怎麼建立的          2.解耦,將構建的過程和表示分離開來 Builder模式的使用場景         1.相同的方法,不同的執行順序,產生不同的時間結果時。         2.多

Java設計模式-建造者(Builder)模式

最近在看Mybatis的原始碼, 在閱讀解析 XML 配置檔案的過程中, 發現使用到了建造者(Builder)模式。 因此, 打算重溫一下該設計模式。 由來 假設我們需要畫一個小人, 我們可能會有以下的建構函式定義: public Person(HeadType headType, HairType hair

Java 設計模式——建造者模式Builder Pattern)

  前言 一、簡介 ​二、實現方式 三、常見第一種方式 (1)一般有以下幾個角色 (2)舉個例子 (3)具體步驟 (4)具體程式碼 三、第二種方式 (1)主要有三個角色:抽象建造者、具體建造者、產品 (2)舉個例子 (3)具體步驟

淺談Java設計模式——建造者模式(Builder)

一、概述         將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。         建造者模式將複雜產品的構建過程封裝分解在不同的方法中,使得建立過程非常清晰,能夠讓我們更加精確的控制複雜產品物件的建立過程,同時它隔離了複雜產品物件的建立

Java設計模式之從[Dota的武器建立]分析生成器(Builder)模式

  Dota可謂是當下最流行的遊戲之一,玩家分為兩隊,分別是天輝(近衛)和夜魘(天災),每隊5個人,通過補刀、殺敵獲取經驗和金錢,金錢可用來購買強大的武器,最終推倒敵方基地則獲勝。我們現在考慮一個最簡單的武器組成元素:武器是由武器名、攻擊力、武器顏色組成,我們要想辦法實現能

java設計模式---builder---構造器

作用:將一個複雜物件的構建與其表示相分離,使得同樣的構建過程可以建立不同的表示。                                                                                                

java設計模式】之 建造者(Builder模式

        我們還是舉上一節的例子:生產汽車。上一節我們通過模板方法模式控制汽車跑起來的動作,那麼需求是無止境的,現在如果老闆又增加了額外的需求:汽車啟動、停止、鳴笛引擎聲都由客戶自己控制,他想要什麼順序就什麼順序,那該如何做呢? 1. 汽車無休止的改造       

android使用Java設計模式建造者模式Builder模式)的寫法:

建造者模式的定義 將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。 這裡給大家分析一下: 定義的前半句說,構造與表示分離,其實就是繼承(或實現)。 兩種工廠模式也都是為某個物件提供一個介面,而且無需指定它們的具體類。