定義:
- 提供了減少對象數(shù)量從而改善應(yīng)用所需的對象結(jié)構(gòu)的方法
說到享元模式捉貌,第一個想到的應(yīng)該就是池技術(shù)了昔穴,String常量池、數(shù)據(jù)庫連接池剧蚣、緩沖池等等都是享元模式的應(yīng)用支竹,所以說享元模式是池技術(shù)的重要實現(xiàn)方式。
比如創(chuàng)建字符串對象時, 如果每次都需要創(chuàng)建一個新的字符串對象的話鸠按,內(nèi)存開銷會很大礼搁,所以如果第一次創(chuàng)建了字符串對象“hello“,下次再創(chuàng)建相同的字符串”hello“時目尖,只需把它的引用指向”hello“即可馒吴,這樣就實現(xiàn)了字符串在內(nèi)存中的共享。
類型:
- 結(jié)構(gòu)型
使用場景
- 常常應(yīng)用于系統(tǒng)底層的開發(fā), 提高系統(tǒng)性能
- 系統(tǒng)有大量相似對象, 需要緩沖池的場景
coding
當(dāng)前社會男多女少, 共享女朋友勢在必行.
以下代碼不做解釋,請自行體會.
public class GirlFriend {
private String id;
private String name;
}
public class FlyweightGirlFriendFactory {
private static Map<String, GirlFriend> map = new HashMap<>(16);
private static Set<String> all;
static {
map.put("5", new GirlFriend("5", "女朋友5號"));
map.put("4", new GirlFriend("4", "女朋友4號"));
map.put("3", new GirlFriend("3", "女朋友3號"));
map.put("2", new GirlFriend("2", "女朋友2號"));
map.put("1", new GirlFriend("1", "女朋友1號"));
all = map.keySet();
}
public static GirlFriend getGirlFriend(String id){
if(!all.contains(id)){
throw new RuntimeException("這個女朋友不出租");
}else if(!map.containsKey(id)){
throw new RuntimeException("這個女朋友被租出去了,還沒還回來!");
}
return map.remove(id);
}
public static void returnGirlFriend(GirlFriend girlFriend){
if(!all.contains(girlFriend.getId())){
throw new RuntimeException("emmm....");
}
map.put(girlFriend.getId(), girlFriend);
}
}
寫完感覺怪怪的..., 好像有哪里不對勁
源碼中的應(yīng)用
除了剛才提到的String連接池之外, 開發(fā)中最常用的Integer類,也應(yīng)用了享元模式
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer 會默認緩存-128-127之間的數(shù)字(可以通過jvm參數(shù)改變這個值),存放到一個數(shù)組中, 因為這些數(shù)字是非常常用的, 復(fù)用這些對象可以減少重復(fù)創(chuàng)建的資源消耗.
優(yōu)點:
- 減少對象的創(chuàng)建, 提高運行效率
- 降低內(nèi)存中對象的數(shù)量, 節(jié)省系統(tǒng)內(nèi)存
缺點:
- 線程安全使用共享的對象, 會帶來線程安全問題
- 增加了系統(tǒng)的復(fù)雜度