這樣做有幾個特點:
- 可以確保在物件建構前設定所有建構時所需要的資訊
- 統一參數設定時機
- config class中對於optional的參數可以有default值
- 設定參數時可以有很大的自由度不用依照constructor規定的參數順序.
- 不代表之後不能變動參數,還是可以加入function 如MyClass.setNewHeight()
用法:
//usage
//為何要使用Builder與其實作後面說明
MyClassConfig config = MyClassConfig.Builder()
.setHeight(100)
.setWidth(50)
.setXXX(...)
.setYYY(...)
.build();
MyClass mc = new MyClass(config);
//constructor
MyClass(MyClassConfig config)
{
this.height = config.height;
this.width = config.width;
//other initialization
...
}
接下來介紹config class的實作,架構如下:
public class MyClassConfig {
//1.config class fields
...
//2.config class constructor
...
//3.static inner builder class:
public static class Builder
{
// 3.1 builder fields
...
// 3.2 builder constructor
...
// 3.3 builder setter
...
// 3.4 build() function
...
} // end of builder
}//end of MyClassConfig
1. config class fields
//首先定義fields,使用final qualifier來確保config建構的時候要完成全部的設定
final int height;
final int width;
...
使用final qualifier有兩個用意
- 確保全部的設定在config建構的時候就會完成
- MyClass要可以直接存取這些fields所以不能是private但又不希望config建構後fields還會被更動
(ps2. final 變數除了在宣告的時候直接assign值外唯一的設定機會是在constructor中)
藉由Builder的幫助來建立fields為final的config class
2.config class constructor
config class的constructor吃一個Builder物件作為參數
public MyClassConfig(Builder pBuilder)
{
this.height = pBuilder.height;
this.width = pBuilder.width;
...
}
3.static inner builder class
這邊加上static是因為static inner class不用reference到outer class 的instance,才可以直接用以下方式建立:
new MyClassConfig.Builder();
最後是builder 的實作
public static class Builder{
//3.1 builder fields
private int height;
//可以在這邊設定default value,如果build過程中沒有被更改,default value會被assign到最後build出來的config class中
private int width = 100;
//3.2 builder constructor
//如果建立config的時候需要一些外部資訊可以當作builder constructor的參數傳入
public Builder(){};
//3.3 builder setter
//設定config參數的functions, 回傳自己是為了可以達到method chaining的效果
//i.e., builder.setHeight(100).setWidth(100).build();
public Builder setHeight(int h)
{
this.height = h;
return this;
}
public Builder setWidth(int w)
{
this.width = w;
return this;
}
//3.4 build function
//最後建立出config的function
public MyClassConfig build()
{
return new MyClassConfig(this);
}
}
大概就是這樣,最後附上一段之前寫的code作為範例
package itri.u9lab.towolf.ratiofixer;
public class RatioLayoutConfig {
final int virtualWidth;
final int virtualHeight;
final boolean isFullScreenMode;
/*
* constructor
*/
public RatioLayoutConfig(Builder pBuilder)
{
this.virtualHeight = pBuilder.virtualHeight;
this.virtualWidth = pBuilder.virtualWidth;
this.isFullScreenMode = pBuilder.isFullScreenMode;
}
/*
* config builder
*/
public static class Builder
{
private int virtualWidth = 768;
private int virtualHeight =1230;
boolean isFullScreenMode = false;
public Builder()
{
}
public Builder setVirtualSize(int pWidth,int pHeight)
{
virtualWidth = pWidth;
virtualHeight = pHeight;
return this;
}
public Builder setFullScreen(boolean mode)
{
isFullScreenMode = mode;
return this;
}
public RatioLayoutConfig build()
{
return new RatioLayoutConfig(this);
}
}//end of builder
public static RatioLayoutConfig getDefaultConfig()
{
return new Builder().setFullScreen(false).setVirtualSize(768, 1230).build();
}
}
沒有留言:
張貼留言