編輯:關於Android編程
這篇博客我們來介紹一下建造者模式(Builder Pattern),建造者模式又被稱為生成器模式,是創造性模式之一,與工廠方法模式和抽象工廠模式不同,後兩者的目的是為了實現多態性,而 Builder 模式的目的則是為了將對象的構建與展示分離。Builder 模式是一步一步創建一個復雜對象的創建型模式,它允許用戶在不知道內部構建細節的情況下,可以更精細地控制對象的構造流程。一個復雜的對象有大量的組成部分,比如汽車它有車輪、方向盤、發動機、以及各種各樣的小零件,要將這些部件裝配成一輛汽車,這個裝配過程無疑會復雜,對於這種情況,為了實現在構建過程中對外部隱藏具體細節,就可以使用 Builder 模式將部件和組裝過程分離,使得構建過程和部件都可以自由擴展,同時也能夠將兩者之間的耦合降到最低。
將一個復雜對象的構建和它的表示分離,使得同樣的構建過程可以創建不同的表示。Builder 模式適用的使用場景:
相同的方法,不同的執行順序,產生不同的事件結果;多個部件或零件,都可以裝配到一個對象中,但是產生的運行結果又不相同時;產品類非常復雜,或者產品類中的調用順序不同產生不同的作用,這個時候使用建造者模式非常適合;當初始化一個對象特別復雜,如參數多,且很多參數都具有默認值時。在實際開發過程中,Builder 模式可以使用工廠模式或者任一其他創建型模式去生成自己的指定組件,Builder 模式也是實現 fluent interface 一種非常好的方法。
Builder 模式的 uml 類圖如下所示:
有四個角色:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NClByb2R1Y3QgsvrGt8Sjv+my+sa3tcTP4LnYwOCju0J1aWxkZXIgvdO/2rvys+nP88Dguea3trL6xre1xNfpvP6jrNK7sOPKx9PJ19PA4Mq1z9a+38zltcTX6bz+uf2zzKOs0OjSqtei0uK1xMrH1eK49r3HyavU2sq1vMrKudPDuf2zzNbQv8nS1MqhwtSjrNfuteTQzbXEvs3Kx8/xIEFsZXJ0RGlhbG9nLkJ1aWxkZXIg0rvR+aOsyqHC1CBCdWlsZGVyINDpxOLA4KOsvasgQ29uY3JldGVCdWlsZGVyINC0s8nSu7j2vrLMrMTasr/A4KO7Q29uY3JlYXRlQnVpbGRlciDA4L7fzOW1xCBCdWlsZGVyIMDgo7tEaXJlY3RvciDA4M2z0rvX6dewuf2zzKOszazR+da1tcPXotLitcTKx6Os1NrP1sq1v6q3orn9s8zW0KOsRGlyZWN0b3IgvcfJq9Kyvq2zo7vhsbvKocLUo6y2+NaxvdPKudPD0ru49iBCdWlsZGVyIMC0vfjQ0LbUz/O1xNfp17CjrNXiuPYgQnVpbGRlciDNqLOjzqrBtMq9tffTw6Os0rK+zcrHyc/D5szhtb21xCA8YSBocmVmPQ=="https://en.wikipedia.org/wiki/Fluent_interface">fluent interface ,它的關鍵點是每個 setter 方法都返回自身,也就是 return this,這樣就使得 setter 方法可以鏈式調用,最典型的仍然是 AlertDialog.Builder 類,使用這種方式不僅去除了 Director 角色,使得整個結構更加簡單,也能對 Product 對象的組件過程有著更精細的控制。
據此我們可以寫出 Builder 模式的通用代碼:
Product.class
public class Product {
public int partB;
public int partA;
public int getPartA() {
return partA;
}
public void setPartA(int partA) {
this.partA = partA;
}
public int getPartB() {
return partB;
}
public void setPartB(int partB) {
this.partB = partB;
}
@Override
public String toString() {
return "partA : " + partA + " partB : " + partB;
}
}
產品類在此聲明了兩個 setter 方法,然後是 Builder 相關類:
Builder.class
public abstract class Builder {
public abstract void buildPartA(int partA);
public abstract void buildPartB(int partB);
public abstract Product build();
}
ConcreteBuilder.class
public class ConcreteBuilder extends Builder{
private Product product = new Product();
@Override
public void buildPartA(int partA) {
product.setPartA(partA);
}
@Override
public void buildPartB(int partB) {
product.setPartB(partB);
}
@Override
public Product build() {
return product;
}
}
Builder 這兩個類用來封裝對 Product 屬性的設置,最後在 build 方法中返回設置完屬性的 Product 對象,最後是 Director 角色:
Director.class
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct(int partA, int partB) {
builder.buildPartA(partA);
builder.buildPartB(partB);
}
}
封裝了 Builder 對象,最後是測試程序:
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct(1, 2);
Product product = builder.build();
Log.e("shawn", product.toString());
break;
運行結果
com.android.builderpattern E/shawn: partA : 1 partB : 2
代碼一目了然,這裡需要提到的一點是針對不同的產品可以去構建不同的 ConcreteBuilder 類,使得一個 ConcreteBuilder 類對應一個 Product 類,這點和工廠方法模式很類似,我們後面也會介紹到他們兩者之間的區別。
Builder 模式在實際開發中出現和使用的頻率也是很高的,比如上面提到的 AlertDialog.Builder ,還比如非常有名的第三方開源框架 Universal-Image-Loader 庫中的 ImageLoaderConfig ,他們都是使用的靜態內部 Builder 類。
這裡的 demo 也使用最簡單的內部靜態 Builder 類去實現,精簡完之後只有 ConcreteBuilder 和 Product 角色,並且使用鏈式調用去實現上面提到的 fluent interface:
Computer.class
public class Computer {
private String CPU;
private String GPU;
private String memoryType;
private int memorySize;
private String storageType;
private int storageSize;
private String screenType;
private float screenSize;
private String OSType;
public static class Builder {
// Optional parameters - initialize with default values
private String CPU = "inter-i3";
private String GPU = "GTX-960";
private String memoryType = "ddr3 1666MHz";
private int memorySize = 8;//8GB
private String storageType = "hdd";
private int storageSize = 1024;//1TB
private String screenType = "IPS";
private float screenSize = 23.8f;
private String OSType = "Windows 10";
public Builder() {
}
public Builder setCPU(String CPU) {
this.CPU = CPU;
return this;
}
public Builder setGPU(String GPU) {
this.GPU = GPU;
return this;
}
public Builder setMemoryType(String memoryType) {
this.memoryType = memoryType;
return this;
}
public Builder setMemorySize(int memorySize) {
this.memorySize = memorySize;
return this;
}
public Builder setStorageType(String storageType) {
this.storageType = storageType;
return this;
}
public Builder setStorageSize(int storageSize) {
this.storageSize = storageSize;
return this;
}
public Builder setScreenType(String screenType) {
this.screenType = screenType;
return this;
}
public Builder setScreenSize(float screenSize) {
this.screenSize = screenSize;
return this;
}
public Builder setOSType(String OSType) {
this.OSType = OSType;
return this;
}
public Computer create() {
return new Computer(this);
}
}
private Computer(Builder builder) {
CPU = builder.CPU;
GPU = builder.GPU;
memoryType = builder.memoryType;
memorySize = builder.memorySize;
storageType = builder.storageType;
storageSize = builder.storageSize;
screenType = builder.screenType;
screenSize = builder.screenSize;
OSType = builder.OSType;
}
}
Computer 為產品類,它有一個 Builder 的靜態內部類用於設置相關屬性,測試代碼:
Computer computer = new Computer.Builder()
.setCPU("inter-skylake-i7")
.setGPU("GTX-Titan")
.setMemoryType("ddr4-2133MHz")
.setMemorySize(16)
.setStorageType("ssd")
.setStorageSize(512)
.setScreenType("IPS")
.setScreenSize(28)
.setOSType("Ubuntu/Window10")
.create();
這裡需要提到的關鍵點是關於相關屬性的默認值問題:
對於必要的屬性值,無法給出其默認值的最好是通過 Builder 類的構造函數傳入,比如 AlertDialog.Builder 類的 Context,這樣也能防止使用時的疏忽;對於非必要屬性來說,最好是為其生成一個默認的屬性值,這樣使用者只用設置需要更改的屬性即可;每個 setter 函數都加上 return this 用來實現優美的 fluent interface 設計。
Builder 模式在 Android 開發中也很常用,通常作為配置類的構建器將配置的構建和表示分離開來,同時也將配置從目標類中隔離開來,避免了過多的 setter 方法。Builder 模式比較常見的實現形式是通過調用鏈實現,這樣的方式也會使得代碼更加簡潔和易懂,而且同時也可以避免了目標類被過多的接口“污染”。
Builder 模式的優點:
Builder 模式和工廠方法模式都是屬於創建型模式,他們有一些共同點:這兩種設計模式的都將一個產品類對象的創建過程封裝起來,讓客戶端從具體產品類的生成中解耦,不必了解產品類構造的細節。但是其實他們兩種設計模式還是有很多不同點:
Builder 模式允許對象的創建通過多個步驟來創建,而且可以改變這個過程,也可以選擇需要改變的屬性;工廠方法模式不一樣,它只有一個步驟,也就無法改變這個過程,更加無法選擇性改變屬性了;Builder 模式的目的是將復雜對象的構建和它的表示分離;而工廠方法模式則是定義一個創建對象的接口,由子類決定要實例化的類是哪一個,將實例化推遲到子類;最明顯的當然還是代碼的差異,Builder 模式中客戶端可以調用 set 方法,而工廠方法模式只能調用工廠類提供的相關方法。其次是 uml 類圖的差異:
https://github.com/zhaozepeng/Design-Patterns/tree/master/BuilderPattern
在tomcat6.0的webappsROOT下放一個.exe的可執行文件(若放.mp3、.jpg等格式的文件可能下載過程出現損壞還是可以查看的,若是.exe可執行文件下載
一、需要下載安裝的東西1. 文件下載網上也有挺多安裝教程的,這裡我提供我的安裝方法。Win10 64位。一些文件我在後面打包。2016.9.12號本人安裝記錄。SDK:
1、先推薦一個輕量級緩存框架——ACache(ASimpleCache)ACache介紹:ACache類似於SharedPrefere
介紹 在谷歌的官網我們可以看到它是這樣介紹的:RecyclerView is a more advanced and flexible version of List