国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android編程設(shè)計(jì)模式之Builder模式實(shí)例詳解

2019-12-12 01:25:53
字體:
供稿:網(wǎng)友

本文實(shí)例講述了Android編程設(shè)計(jì)模式之Builder模式。分享給大家供大家參考,具體如下:

一、介紹

Builder模式是一步一步創(chuàng)建一個(gè)復(fù)雜對(duì)象的創(chuàng)建型模式,它允許用戶在不知道內(nèi)部構(gòu)建細(xì)節(jié)的情況下,可以更精細(xì)的控制對(duì)象的構(gòu)造流程。該模式是為了將構(gòu)建復(fù)雜對(duì)象的過程和它的部件解耦,使得構(gòu)建過程和部件的表示隔離開來。

因?yàn)橐粋€(gè)復(fù)雜的對(duì)象有很多大量組成部分,例如車,有車輪、方向盤、發(fā)動(dòng)機(jī),還有各種小零件等,如何將這些部件裝配成一輛汽車,這個(gè)裝配過程很漫長,也很復(fù)雜,對(duì)于這種情況,為了在構(gòu)建過程中對(duì)外部隱藏實(shí)現(xiàn)細(xì)節(jié),就可以使用Builder模式將部件和組裝過程分離,使得構(gòu)建過程和部件都可以自由擴(kuò)展,兩者之間的耦合也降到最低。

二、定義

將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

三、使用場景

(1)相同的方法,不同的執(zhí)行順序,產(chǎn)生不同的事件結(jié)果時(shí)。

(2)多個(gè)部件或零件,都可以裝配到一個(gè)對(duì)象中,但是產(chǎn)生的運(yùn)行結(jié)果又不相同時(shí)。

(3)產(chǎn)品類非常復(fù)雜,或者產(chǎn)品類中的調(diào)用順序不同產(chǎn)生了不同的作用,這個(gè)時(shí)候使用建造者模式非常合適。

(4)當(dāng)初始化一個(gè)對(duì)象特別復(fù)雜,如參數(shù)多,且很多參數(shù)都具有默認(rèn)值時(shí)。

四、Builder模式的UML類圖

角色介紹:

Product產(chǎn)品類――產(chǎn)品的抽象類;

Builder――抽象Builder類,規(guī)范產(chǎn)品的組建,一般是由子類實(shí)現(xiàn)具體的組建過程;

ConcreateBuilder――具體的Builder類;

Director――統(tǒng)一組裝過程;

五、Builder模式的簡單實(shí)現(xiàn)

計(jì)算機(jī)的組裝過程較為復(fù)雜,并且組裝順序是不固定的,為了易于理解,我們把計(jì)算機(jī)的組裝過程簡化為構(gòu)建主機(jī)、設(shè)置操作系統(tǒng)、設(shè)置顯示器3個(gè)部分,然后通過Director和具體的Builder來構(gòu)建計(jì)算機(jī)對(duì)象。

示例代碼:

/** * 計(jì)算機(jī)抽象類,即Product角色 */public abstract class Computer {  protected String mBoard;  protected String mDisplay;  protected String mOS;  protected Computer(){}  /**   * 設(shè)置主板   * @param board   */  public void setBoard(String board){    this.mBoard = board;  }  /**   * 設(shè)置顯示器   * @param display   */  public void setDisplay(String display){    this.mDisplay = display;  }  /**   * 設(shè)置操作系統(tǒng)   */  public abstract void setOS();  @Override  public String toString(){    return "Computer [mBoard=" + mBoard + ", mDisplay=" + mDisplay + ", mOS=" + mOS + "]";  }}
/** * 具體的Computer類,Macbook */public class Macbook extends Computer {  protected Macbook(){}  @Override  public void setOS() {    mOS = "Mac OS X 10";  }}
/** * 抽象Builder類 */public abstract class Builder {  /**   * 設(shè)置主機(jī)   * @param board   */  public abstract void buildBoard(String board);  /**   * 設(shè)置顯示器   * @param display   */  public abstract void buildDisplay(String display);  /**   * 設(shè)置操作系統(tǒng)   */  public abstract void buildOS();  /**   * 創(chuàng)建Computer   * @return   */  public abstract Computer create();}
/** * 具體的Builder類,MacbookBuilder */public class MacbookBuilder extends Builder {  private Computer mComputer = new Macbook();  @Override  public void buildBoard(String board) {    mComputer.setBoard(board);  }  @Override  public void buildDisplay(String display) {    mComputer.setDisplay(display);  }  @Override  public void buildOS() {    mComputer.setOS();  }  @Override  public Computer create() {    return mComputer;  }}
/** * Director類,負(fù)責(zé)構(gòu)造Computer */public class Director {  Builder mBuilder = null;  public Director(Builder builder){    mBuilder = builder;  }  /**   * 構(gòu)建對(duì)象   * @param board 主板   * @param display 顯示器   */  public void construct(String board, String display){    mBuilder.buildBoard(board);    mBuilder.buildDisplay(display);    mBuilder.buildOS();  }}
/** * 測試代碼 */public class Test {  public static void main(String[] args){    //構(gòu)建器    Builder builder = new MacbookBuilder();    //Director    Director pcDirector = new Director(builder);    //封裝構(gòu)建過程    pcDirector.construct("英特爾主板","Retina顯示器");    //構(gòu)建計(jì)算機(jī),輸出相關(guān)信息    System.out.println("Computer Info : " + builder.create().toString());  }}

輸出結(jié)果:

復(fù)制代碼 代碼如下:
Computer Info : Computer [mBoard=英特爾主板, mDisplay=Retina顯示器, mOS=Mac OS X 10]

上述示例中,通過具體的MacbookBuilder來構(gòu)建Macbook對(duì)象,而Director封裝了構(gòu)建復(fù)雜產(chǎn)品對(duì)象的過程,對(duì)外隱藏構(gòu)建細(xì)節(jié)。Builder與Director一起將一個(gè)復(fù)雜的對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的對(duì)象。

值得注意的是,在現(xiàn)實(shí)的開發(fā)過程中,Director角色經(jīng)常會(huì)被省略。而直接使用一個(gè)Builder來進(jìn)行對(duì)象的組裝,這個(gè)Builder通常為鏈?zhǔn)秸{(diào)用,它的關(guān)鍵點(diǎn)是每個(gè)setter方法都返回自身,也就是return this,這樣就使得setter方法可以鏈?zhǔn)秸{(diào)用,代碼大致如下:

new TestBuilder()  .setA("A")  .create();

通過這種形式不僅去除了Director角色,整個(gè)結(jié)構(gòu)也更加簡單,也能對(duì)Product對(duì)象的組裝過程有更精細(xì)的控制。

六、Builder模式變種――鏈?zhǔn)秸{(diào)用

示例代碼:

public class User {  private final String name;     //必選  private final String cardID;    //必選  private final int age;       //可選  private final String address;   //可選  private final String phone;    //可選  private User(UserBuilder userBuilder){    this.name=userBuilder.name;    this.cardID=userBuilder.cardID;    this.age=userBuilder.age;    this.address=userBuilder.address;    this.phone=userBuilder.phone;  }  public String getName() {    return name;  }  public String getCardID() {    return cardID;  }  public int getAge() {    return age;  }  public String getAddress() {    return address;  }  public String getPhone() {    return phone;  }  public static class UserBuilder{    private final String name;    private final String cardID;    private int age;    private String address;    private String phone;    public UserBuilder(String name,String cardID){      this.name=name;      this.cardID=cardID;    }    public UserBuilder age(int age){      this.age=age;      return this;    }    public UserBuilder address(String address){      this.address=address;      return this;    }    public UserBuilder phone(String phone){      this.phone=phone;      return this;    }    public User build(){      return new User(this);    }  }}

需要注意的點(diǎn):

User類的構(gòu)造方法是私有的,調(diào)用者不能直接創(chuàng)建User對(duì)象。

User類的屬性都是不可變的。所有的屬性都添加了final修飾符,并且在 構(gòu)造方法中設(shè)置了值。并且,對(duì)外只提供getters方法。

Builder的內(nèi)部類構(gòu)造方法中只接收必傳的參數(shù),并且該必傳的參數(shù)使用了final修飾符。

調(diào)用方式:

new User.UserBuilder("Jack","10086")    .age(25)    .address("GuangZhou")    .phone("13800138000")    .build();

相比起前面通過構(gòu)造函數(shù)和setter/getter方法兩種方式,可讀性更強(qiáng)。唯一可能存在的問題就是會(huì)產(chǎn)生多余的Builder對(duì)象,消耗內(nèi)存。然而大多數(shù)情況下我們的Builder內(nèi)部類使用的是靜態(tài)修飾的(static),所以這個(gè)問題也沒多大關(guān)系。

關(guān)于線程安全

Builder模式是非線程安全的,如果要在Builder內(nèi)部類中檢查一個(gè)參數(shù)的合法性,必需要在對(duì)象創(chuàng)建完成之后再檢查

正確示例:

public User build() { User user = new user(this); if (user.getAge() > 120) {  throw new IllegalStateException("Age out of range"); // 線程安全 } return user;}

錯(cuò)誤示例:

public User build() { if (age > 120) {  throw new IllegalStateException("Age out of range"); // 非線程安全 } return new User(this);}

七、用到Builder模式的例子

1、Android中的AlertDialog.Builder

private void showDialog(){    AlertDialog.Builder builder=new AlertDialog.Builder(context);    builder.setIcon(R.drawable.icon);    builder.setTitle("Title");    builder.setMessage("Message");    builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() {      @Override      public void onClick(DialogInterface dialog, int which) {        //TODO      }    });    builder.setNegativeButton("Button2", new DialogInterface.OnClickListener() {      @Override      public void onClick(DialogInterface dialog, int which) {        //TODO      }    });    builder.create().show();}

2、OkHttp中OkHttpClient的創(chuàng)建

OkHttpClient okHttpClient = new OkHttpClient.Builder()         .cache(getCache())         .addInterceptor(new HttpCacheInterceptor())         .addInterceptor(new LogInterceptor())         .addNetworkInterceptor(new HttpRequestInterceptor())         .build();

3、Retrofit中Retrofit對(duì)象的創(chuàng)建

Retrofit retrofit = new Retrofit.Builder()     .client(createOkHttp())    .addConverterFactory(GsonConverterFactory.create())     .addCallAdapterFactory(RxJavaCallAdapterFactory.create())     .baseUrl(BASE_URL)     .build();

可見在實(shí)際使用中,均省略掉了Director角色,在很多框架源碼中,涉及到Builder模式時(shí),大多都不是經(jīng)典GOF的Builder模式,而是選擇了結(jié)構(gòu)更加簡單的后者。

八、優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

良好的封裝性,使得客戶端不需要知道產(chǎn)品內(nèi)部實(shí)現(xiàn)的細(xì)節(jié)

建造者獨(dú)立,擴(kuò)展性強(qiáng)

缺點(diǎn):

產(chǎn)生多余的Builder對(duì)象、Director對(duì)象,消耗內(nèi)存

更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開發(fā)入門與進(jìn)階教程》、《Android調(diào)試技巧與常見問題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)

希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 嫩江县| 荆州市| 临沧市| 通辽市| 佛坪县| 万全县| 福安市| 马边| 错那县| 巴南区| 松滋市| 承德市| 桂林市| 望奎县| 比如县| 黑水县| 含山县| 济源市| 同仁县| 芷江| 米易县| 南昌市| 揭东县| 伊吾县| 新绛县| 彩票| 阳春市| 新宁县| 安阳市| 阳曲县| 尼木县| 烟台市| 彩票| 定结县| 梅河口市| 滦平县| 新宾| 沭阳县| 金堂县| 嵊州市| 泰顺县|