引言
本博客的內(nèi)容完全是為記錄自己的一些讀書感悟,如果喜歡可以進(jìn)行閱讀如有問題請指正廷支,謝謝频鉴。
思考
- 什么是構(gòu)造器,什么是靜態(tài)工廠方法恋拍?
- 什么時候用構(gòu)造器垛孔,什么時候用靜態(tài)工廠方法?
靜態(tài)工廠方法和構(gòu)造器
靜態(tài)工廠方法的優(yōu)點:
- 靜態(tài)方法是有名稱的施敢,有具體的名稱更易于使用者去閱讀和了解其功能似炎。如果我需要多個構(gòu)造器時辛萍,使用靜態(tài)工廠方法可能是最好的悯姊。多個構(gòu)造器除了參數(shù)類型等區(qū)分不同的功能再沒有其他的方式羡藐,極易用錯。但是靜態(tài)的構(gòu)工廠方法可以為每一個提供不同的名稱悯许,很容易區(qū)分仆嗦。這種情況使用靜態(tài)工廠是個好的實現(xiàn)方式。
- 靜態(tài)工廠方法了解加載機(jī)制的都知道先壕,它不會再每一次調(diào)用時都構(gòu)建一個新的對象瘩扼,對于頻繁調(diào)用時是一個不錯的方式。
- 靜態(tài)工廠方法有返回值垃僚,在某種用途上我們能夠更好的實現(xiàn)集绰。例如后面的構(gòu)建器。
- 實例化參數(shù)類型時更加的簡潔明了谆棺。
//實例化時
Map<String, List<String>> map = new HashMap<String, List<String>>();
//Google Guava提供的靜態(tài)實例化方法
public static<K, V> HashMap<K, V> newHashMap(){
reutrn new HashMap<K, V>();
}
//實例化時
Map<String, List<String>> map = Maps.newHashMap();
靜態(tài)工廠方法的缺點:
- 類如果沒有構(gòu)造器栽燕,就不能被子類去類化。
- 它們與其他的靜態(tài)方法沒什么區(qū)別改淑。API文檔中不會提供靜態(tài)方法的說明碍岔,有時候你可能只看文檔無法知道如何實例化一個類(當(dāng)然看源碼很容易就知道了)
使用構(gòu)建器
- 使用構(gòu)造器是解決靜態(tài)工廠和構(gòu)造器的局限性,它們不能很好的擴(kuò)展到大量的可選擇參數(shù)朵夏。
- 普通的要靈活的使用構(gòu)造的參數(shù)個數(shù)可能要寫大量的構(gòu)造器去處理蔼啦,相當(dāng)?shù)姆爆崱?/li>
- 前期可能使用的參數(shù)較少感覺使用構(gòu)建器反而更復(fù)雜,但是后期擴(kuò)展時很方便仰猖。
構(gòu)建器的實現(xiàn):
public class Build {
private String name;
private Integer age;
private String desc;
public static class BuildForm {
private String name;
private Integer age;
private String desc;
public BuildForm() {
}
public BuildForm nameBuild(String name) {
this.name = name;
return this;
}
public BuildForm ageBuild(Integer age) {
this.age = age;
return this;
}
public BuildForm descBuild(String decs) {
this.desc = decs;
return this;
}
public Build buildData() {
return new Build(this);
}
}
//創(chuàng)建私有構(gòu)造器防止調(diào)用默認(rèn)構(gòu)造器處理和處理內(nèi)部賦值
private Build(BuildForm buildForm){
this.name = buildForm.name;
this.age = buildForm.age;
this.desc = buildForm.desc;
}
@Override
public String toString() {
return "Build{" +
"name='" + name + '\'' +
", age=" + age +
", desc='" + desc + '\'' +
'}';
}
}
構(gòu)建器的使用:
public class Main {
public static void main(String[] argv) {
Build buildOne = new Build.BuildForm()
.nameBuild("AA")
.buildData();
Build buildTwo = new Build.BuildForm()
.nameBuild("BB")
.ageBuild(12)
.buildData();
Build buildThree = new Build.BuildForm()
.nameBuild("CC")
.ageBuild(12)
.descBuild("啊哈哈")
.buildData();
System.out.println(buildOne.toString());
System.out.println(buildTwo.toString());
System.out.println(buildThree.toString());
}
}
測試結(jié)果如下:
Build{name='AA', age=null, desc='null'}
Build{name='BB', age=12, desc='null'}
Build{name='CC', age=12, desc='啊哈哈'}
以上就是一個簡單的構(gòu)建器捏肢,大家可以根據(jù)自己的需求去使用。
單例屬性的強(qiáng)化
私有的構(gòu)造器
就如同我上面代碼中寫到的饥侵,如果不使用私有的構(gòu)造器去處理類鸵赫,雖然我們的實現(xiàn)是單例的,但是使用者完全可以使用默認(rèn)的構(gòu)造器去創(chuàng)建出來新的對象爆捞,有時候就違背我們的初衷奉瘤。
枚舉的方式
我們可以使用枚舉的方式去創(chuàng)建一個單例模式,這樣就不會出現(xiàn)上述的情況煮甥。創(chuàng)建的方式如下代碼:
//創(chuàng)建一個類
public class Factory {
}
//枚舉的方式實例化類
public enum EnumFactory {
DATE;
private Factory factory;
public void buildSingleton(){
factory = new Factory();
}
public Factory getFactory(){
return factory;
}
}
//類的使用
public class Main {
public static void main(String[] argv) {
Factory factory = EnumFactory.DATE.getFactory();
}
}
三種單例的創(chuàng)建模式盗温,枚舉的方式可能是現(xiàn)在做好的方法。
對象的銷毀
內(nèi)存泄露
對象有創(chuàng)建必然存在銷毀成肘,java提供有自己的垃圾回收機(jī)制卖局。但是并不代表java不會出現(xiàn)內(nèi)存泄露。所以我們需要消除過期的對象引用双霍,若過期的對象引用一直存在垃圾回收器就不會去回收資源砚偶。一般這種情況發(fā)生在引用緩存中批销。開發(fā)中要注意這類情況。下面是三種容易發(fā)生內(nèi)存泄露的情況染坯。
- 無意識的泄露均芽,一般是代碼考慮不周全導(dǎo)致,沒有考慮泄露的意識单鹿。
- 緩存中存放的對象掀宋,一般需要去維護(hù),不然容易出現(xiàn)泄露仲锄。
- 監(jiān)聽器和回調(diào)劲妙,這種情況一般是需要維護(hù)對象的長期有效的,但是使用完成如果不進(jìn)行注銷就會出現(xiàn)泄露儒喊。
避免使用終結(jié)方法
java有提供終結(jié)方法來讓開發(fā)者去終結(jié)镣奋,但是終結(jié)方法的線程優(yōu)先級極低,我們并不能去確定終結(jié)方法一定會執(zhí)行怀愧,有不能確定終結(jié)方法執(zhí)行的時間侨颈。當(dāng)然有些情況是需要去使用終結(jié)方法的,例如流的關(guān)閉掸驱,一般要配合try....finally來使用肛搬。
結(jié)束語
一些簡單的介紹,如果要很好的了解建議大家親自去看看這本書毕贼。希望淺薄的理解能對你的開發(fā)有幫助温赔。