Android_物件的建立And建造者模式
作為一個普通的Android的上層開發,最早引以為榮的事情就是自己實現了某些效果,完成了某些自定義控制元件自豪,會使用當前較為流行的開源框架而自豪,比如RxJava retrofit fresco…..
這些天也是不是也反思為毛招聘Android工程師,技能點都是JAVA基本功,深入JVM 資料結構和演算法,說好的招Android開發呢!
地基打不好,樓層蓋不高
曾經浪費掉的光陰,只能今天來彌補,於是最近在閱讀大神推薦的Effective Java.
提高程式碼嚴謹性,提高程式設計思想,copy 永遠是copy ,使用一直是使用,思想是別人demo給不了你的!
–2016年03月20日
-靜態工廠的使用
有些時候我們需要用靜態工廠的方法代替構造器,靜態工廠,例項物件的時候程式碼更容易閱讀,他們有名稱
- 靜態工廠,不必再每次呼叫他們的時候都建立一個新的物件
- 靜態工廠,可以返回原返回型別的任何子型別的物件
- 如下程式碼片段
public class HashMapFactory {
private HashMapFactory() {
}
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
}
我們建立了一個Map的工廠類,於是我們在使用的時候就可以非常便捷
Map<String, String> mTestString;
Map<String, Integer> mTestInteger;
mTestInteger = HashMapFactory.newInstance();
mTestString = HashMapFactory.newInstance();
mTestInteger.put("INTEGER", 12);
mTestInteger.put("INTEGER1" , 13);
mTestString.put("String", "sfsfs");
mTestString.put("String1", "哈哈哈哈");
不管你建立何種型別的map都只需要,newInstance即可
遇到多個構造器引數的時候考慮用builder pattern
是將一個複雜的物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
我們Android程式設計師其實經常碰見這類程式碼,比如我們建立一個dialog的時候,
//顯示基本的AlertDialog
private void showDialog(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon);
builder.setTitle( "Title" );
builder.setMessage( "Message" );
builder.setPositiveButton( "Button1" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setTitle( "點選了對話方塊上的Button1" );
}
});
builder.setNeutralButton( "Button2" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setTitle( "點選了對話方塊上的Button2" );
}
});
builder.setNegativeButton( "Button3" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setTitle( "點選了對話方塊上的Button3" );
}
});
builder.create().show(); // 構建AlertDialog, 並且顯示
}
上面的程式碼我們再熟悉不過了,我們要彈出一個對話方塊,
對話方塊中有很多引數,並不是我們構造的時候都要傳入的,他分為
必傳引數和可選引數,比如context 是必傳的,剩下的title和icon 和message都是可選的還有按鈕的數量,
再比如我們用的網路請求庫retrofit,可以選擇設定header,gosonfactory ,等
為了更好的理解建造者模式中的各個角色,我們就仿造android的alertdialog的寫法,自己做一個建造者,來呼叫下
首選我們寫一個House類,我們來蓋房子
因為我們要用建造者來例項化不同的房子,所以,
- 我們House的構造就必須私有化,不提供給外界呼叫,我們呼叫的時候直接是用類名,呼叫的建造者的build方法,所以我們需要在類的內部提供一個static的建造者
- 將靜態的建造者提供例項化各種屬性類別的方法,返回當前的建造者
最後提供一個公開的build方法返回設定好各種屬性的當前的物件
我們在程式碼中看一下分工,
public class House {
// 必選的引數
private String foundation;
private String material;
// 可選的引數
private String bigDoor;
private String setp;
private String ceilingLamp;
// 內部提供一個靜態的builder類,提供引數的設定,以及返回例項
public static class Builder {
private String foundation;
private String material;
// 可選引數賦預設值
private String bigDoor = "普通大門";
private String setp = "普通臺階";
private String ceilingLamp = "普通吊燈";
/**
* 構造引數中傳遞必選引數
*
* @param foundation
* @param material
*/
public Builder(String foundation, String material) {
this.foundation = foundation;
this.material = material;
}
// 可選引數的可選builder方法
public Builder bigDoor(String bigDoor) {
this.bigDoor = bigDoor;
return this;
}
public Builder setP(String setp) {
this.setp = setp;
return this;
}
public Builder ceilingLamp(String ceilingLamp) {
this.ceilingLamp = ceilingLamp;
return this;
}
// 上述必選和可選的引數全部配置完畢,最後開始建造房子,返回當前房子物件
public House build() {
return new House(this);
}
}
// 建構函式私有化返回當前的物件
private House(Builder builder) {
this.foundation = builder.foundation;
this.material = builder.material;
this.bigDoor = builder.bigDoor;
this.setp = builder.setp;
this.ceilingLamp = builder.ceilingLamp;
}
}
最後我們在我們的類中使用下我們的建造者,給我和你分別建立一個house,
private static void testBuilderPattern() {
// 使用的時候因為我們的類已經私有化建構函式,所以只能通過New 出來當前類的建造者來配置,和builder
Car mCar = new Car.Builder("高階輪胎", "進口引擎", "24k金方向盤")
.graffiti("全裸塗鴉")
.sticker("豪放貼紙")
.build();
// 不傳遞可選引數
Car otherCar = new Car.Builder("普通輪胎", "大眾引擎", "拖拉機改造方向盤")
.build();
House mHouse = new House.Builder("350平米地基", "全進口材料")
.bigDoor("鍍金雙開大門")
.ceilingLamp("南非鑲鑽吊燈")
.setP("進口大理石臺階")
.build();
House otherHouse = new House.Builder("10平米廁所旁地基", "國內高含量超標材料")
.bigDoor("破大門")
.ceilingLamp("普通燈泡")
.setP("藍翔挖掘的紅磚臺階")
.build();
}
這樣就一路瞭然,我們的必選引數通過建造者的建構函式傳入,可選引數分別呼叫了當前引數建造方法,在全部的引數配置完畢之後,我們呼叫下build()方法就返回了當前的class物件,
?為什麼呼叫build方法沒new當前物件就能返回當前的class呢
答案就是,我們build方法在內部呼叫了 new Instance()方法.並且把配置好全部屬性的builder傳入到構造中,並且把builder的屬性給我們的class屬性賦值,
// 配置完畢執行build方法返回當前具備屬性的物件
public Car build() {
// 這呼叫了下面的私有構造方法,接受當前配置好屬性的builder
return new Car(this);
}
// 這裡傳入了配置好屬性的builder給我們的class屬性賦值,
private Car(Builder builder) {
this.engine = builder.engine;
this.graffiti = builder.graffiti;
this.sticker = builder.sticker;
this.tires = builder.tires;
this.wheel = builder.wheel;
}
好了我們看下結果,我的房子和我的車都是什麼屬性
總結 :如果類的構造器或者靜態工廠中具有多個引數,設計這種類,Builder模式就是個不錯的選擇,特別有很多可選引數或者元素的時候,使用傳統的構造器或者過載,並沒有Builder模式簡單讓客戶端程式碼更容易閱讀和編寫…
謝謝您的閱讀!!