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

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

Android編程設計模式之Builder模式實例詳解

2019-10-22 18:19:16
字體:
供稿:網(wǎng)友

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

一、介紹

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

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

二、定義

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

三、使用場景

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

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

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

(4)當初始化一個對象特別復雜,如參數(shù)多,且很多參數(shù)都具有默認值時。

四、Builder模式的UML類圖

角色介紹:

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

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

ConcreateBuilder——具體的Builder類;

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

Android,Builder模式,設計模式

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

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

示例代碼:

/** * 計算機抽象類,即Product角色 */public abstract class Computer {  protected String mBoard;  protected String mDisplay;  protected String mOS;  protected Computer(){}  /**   * 設置主板   * @param board   */  public void setBoard(String board){    this.mBoard = board;  }  /**   * 設置顯示器   * @param display   */  public void setDisplay(String display){    this.mDisplay = display;  }  /**   * 設置操作系統(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 {  /**   * 設置主機   * @param board   */  public abstract void buildBoard(String board);  /**   * 設置顯示器   * @param display   */  public abstract void buildDisplay(String display);  /**   * 設置操作系統(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類,負責構造Computer */public class Director {  Builder mBuilder = null;  public Director(Builder builder){    mBuilder = builder;  }  /**   * 構建對象   * @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){    //構建器    Builder builder = new MacbookBuilder();    //Director    Director pcDirector = new Director(builder);    //封裝構建過程    pcDirector.construct("英特爾主板","Retina顯示器");    //構建計算機,輸出相關信息    System.out.println("Computer Info : " + builder.create().toString());  }}

輸出結(jié)果:

 

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

 

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

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

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

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

六、Builder模式變種——鏈式調(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);    }  }}

需要注意的點:

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

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

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

調(diào)用方式:

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

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

關于線程安全

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

正確示例:

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

錯誤示例:

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對象的創(chuàng)建

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

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

八、優(yōu)缺點

優(yōu)點:

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

建造者獨立,擴展性強

缺點:

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

希望本文所述對大家Android程序設計有所幫助。


注:相關教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 武山县| 定结县| 囊谦县| 柞水县| 长寿区| 沅江市| 德州市| 灵石县| 新和县| 股票| 磐石市| 淮北市| 平度市| 肥城市| 社旗县| 吉隆县| 山东省| 北宁市| 苏尼特右旗| 邵阳县| 栾川县| 和平区| 承德县| 儋州市| 芮城县| 泰州市| 衡阳市| 嘉峪关市| 伊川县| 沾化县| 溧水县| 永年县| 二连浩特市| 临桂县| 雅安市| 宿迁市| 安图县| 东乡族自治县| 梁河县| 景德镇市| 南康市|