最近看到一段代碼,感覺寫得非常好慧妄,它的功能是帶參數(shù)啟動(dòng) Activity:
public class SecondActivity extends Activity {
public static void actionStart(Context context, String data1, String data2) {
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
...
}
使用靜態(tài)方法的好處是什么呢?首先是一目了然剪芍,SecondActivity 需要的數(shù)據(jù)在方法參數(shù)中全部體現(xiàn)出來了塞淹,這樣即使不閱讀 SecondActivity 的代碼,不用詢問負(fù)責(zé)編寫 SecondActivity 的同事罪裹,也可以清楚地知道啟動(dòng) SecondActivity 需要傳遞哪些數(shù)據(jù)饱普。另外,這樣寫還簡(jiǎn)化了啟動(dòng) Activity 的代碼状共,調(diào)用者只需要使用一行代碼就可以啟動(dòng) Activity套耕,真的是非常簡(jiǎn)便!
SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
這讓我想到了《Effective Java 第2版》書中講的一條經(jīng)驗(yàn):考慮使用靜態(tài)工廠方法代替構(gòu)造器口芍。這里的靜態(tài)工廠方法與設(shè)計(jì)模式中的工廠方法模式不同箍铲,它是用于創(chuàng)建當(dāng)前類對(duì)象的靜態(tài)方法。
提供靜態(tài)工廠方法而不是公有的構(gòu)造器的好處是什么呢鬓椭?
-
靜態(tài)工廠方法有名稱颠猴,可以清晰地閱讀。如果構(gòu)造器的參數(shù)本身沒有確切地描述返回的對(duì)象小染,那么具有適當(dāng)名稱的靜態(tài)工廠方法會(huì)更容易使用翘瓮。
舉個(gè)栗子:Executors 類里面有一系列構(gòu)建線程池的靜態(tài)工廠方法,根據(jù)方法名就能知道返回的線程池的類型裤翩,清晰簡(jiǎn)潔资盅,對(duì)使用者來說非常友好。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
-
不必在每次調(diào)用靜態(tài)工廠方法的時(shí)候都創(chuàng)建一個(gè)新對(duì)象踊赠。這使得不可變類可以使用預(yù)先構(gòu)建好的實(shí)例呵扛,或者將實(shí)例緩存起來進(jìn)行復(fù)用,從而避免創(chuàng)建不必要的重復(fù)對(duì)象筐带。
舉個(gè)栗子:Boolean 類的 valueOf 方法今穿,返回預(yù)先構(gòu)建的緩存的實(shí)例,實(shí)例的復(fù)用提升了軟件的性能伦籍。
public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false); public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
-
靜態(tài)工廠方法可以返回原返回類型的任何子類型的對(duì)象蓝晒,這樣我們?cè)谶x擇返回對(duì)象的類時(shí)就有了更好的靈活性腮出。
舉個(gè)栗子:EnumSet 類的 noneOf 方法返回一個(gè)空的枚舉集合,類型是 EnumSet 的子類芝薇,這樣根據(jù)不同的條件就能得到不同的實(shí)現(xiàn)類的實(shí)例胚嘲,提高了方法的靈活性。
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { if (!elementType.isEnum()) { throw new ClassCastException(elementType.getClass().getName() + " is not an Enum"); } E[] enums = Enum.getSharedConstants(elementType); if (enums.length <= 64) { return new MiniEnumSet<E>(elementType, enums); } return new HugeEnumSet<E>(elementType, enums); }
-
使用靜態(tài)工廠方法創(chuàng)建參數(shù)化類型的實(shí)例洛二,代碼會(huì)變得非常簡(jiǎn)潔
舉個(gè)栗子:使用靜態(tài)工廠方法 newInstance 創(chuàng)建帶參數(shù)的 Fragment馋劈,參數(shù)清晰、代碼簡(jiǎn)潔灭红,使用起來非常容易侣滩。
public class BlankFragment extends Fragment { public static BlankFragment newInstance(String param1, String param2) { BlankFragment fragment = new BlankFragment(); Bundle args = new Bundle(); args.putString("param1", param1); args.putString("param2", param2); fragment.setArguments(args); return fragment; } ... }
靜態(tài)工廠方法的命名也有標(biāo)準(zhǔn),下面是一些慣用名稱:
- valueOf: 這是類型轉(zhuǎn)換的方法变擒,返回的實(shí)例與它的參數(shù)具有相同的值君珠。
- of:valueOf 的一種更為簡(jiǎn)潔的替代,在 EnumSet 中使用并流行起來娇斑。
- getInstance:返回的實(shí)例是通過方法的參數(shù)來描述的策添,對(duì)于單例來說,返回唯一的實(shí)例毫缆。
- newInstance:像 getInstance 一樣唯竹,但是可以確保返回的每個(gè)實(shí)例都與其他的實(shí)例不同。
- getType:像 getInstance 一樣苦丁,但是在工廠方法處于不用的類中的時(shí)候使用浸颓。
- newType:像 newInstance 一樣,但是在工廠方法處于不用的類中的時(shí)候使用旺拉。
總而言之产上,靜態(tài)工廠方法的優(yōu)勢(shì)還是很明顯的,簡(jiǎn)潔易讀蛾狗,方便使用晋涣。所以在編碼的過程中,還是要考慮使用靜態(tài)工廠方法沉桌,不要一味地使用構(gòu)造器谢鹊。