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