Java設計模式----享元模式(FlyWeight)
阿新 • • 發佈:2019-02-14
1. 享元模式定義:
享元模式是池技術的重要實現原理,定義如下:使用共享物件可以有效的支援大量的細粒度物件
內部狀態:儲存在享元物件內部不隨外部環境改變可以共享出來的資訊
外部狀態:外部狀態是物件得以依賴的一個標記,是隨外部環境改變而變化、不可以共享的狀態
2. 享元模式的角色名稱:
a. 抽象享元角色
簡單地說,就是一個產品的抽象類,它同時定義了物件的內部狀態和外部狀態,以及介面和實現
b. 具體的享元物件
具體的產品類,實現了抽象產品類定義的業務
c. 享元工廠
提供一個池容器,同時提供從池中獲取物件的方法
3. 享元模式通用示例程式碼:
抽象享元角色類:
抽象享元角色類一般是一個抽象類,一般要把外部狀態和內部狀態定義出來,避免子類隨意的擴充套件。public abstract class FlyWeight { //內部狀態 private String intrinsic; private String name; //外部狀態 protected final String extrinsic; //要求享元角色必須接受外部狀態 public FlyWeight(String extrinsic) { this.extrinsic=extrinsic; } //定義業務操作 public abstract void operator(); //內部狀態的getter/setter public String getIntrinsic() { return intrinsic; } public void setIntrinsic(String intrinsic) { this.intrinsic = intrinsic; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
具體的享元角色類:
public class FlyWeight1 extends FlyWeight{
public FlyWeight1(String extrinsic) {
super(extrinsic);
}
@Override
public void operator() {
System.out.println("業務操作方法...內部狀態是:"+super.getIntrinsic());
}
}
享元工廠類:
測試類:public class FlyWeightFactory { private static HashMap<String,FlyWeight> pool=new HashMap<String,FlyWeight>(); public static FlyWeight getInstance(String key){ //需要返回的物件 FlyWeight flyWeight=null; //如果池中存在該物件,直接獲取返回 if(pool.containsKey(key)){ System.out.println(key+"-----池中存在,直接從物件池中取得"); flyWeight=pool.get(key); }else{ //池中不存在此物件,根據外部狀態新建一個物件返回 System.out.println(key+"-----池中不存在,建立物件並放到物件池中"); flyWeight=new FlyWeight1(key); //放置到池中 pool.put(key, flyWeight); } return flyWeight; } /** * 初始化物件池 * @param size */ public static void initObjectPool(int size){ for (int i = 0; i <= size; i++) { FlyWeightFactory.getInstance("物件"+i); } } }
public class Test {
public static void main(String[] args) {
//初始化物件池
FlyWeightFactory.initObjectPool(4);
FlyWeight flyWeight=FlyWeightFactory.getInstance("物件1");
flyWeight.setIntrinsic("這是單獨設定的內部狀態!");
flyWeight.operator();
}
}
結果:
物件0-----池中不存在,建立物件並放到物件池中
物件1-----池中不存在,建立物件並放到物件池中
物件2-----池中不存在,建立物件並放到物件池中
物件3-----池中不存在,建立物件並放到物件池中
物件4-----池中不存在,建立物件並放到物件池中
物件1-----池中存在,直接從物件池中取得
業務操作方法...內部狀態是:這是單獨設定的內部狀態!
4. 享元模式的優點和缺點
享元模式是可以大大減少應用程式建立物件的時間,降低程式記憶體的佔用,增強程式的效能,同時它也大大加大了程式的複雜度,因為需要分離外部狀態和內部狀態。
5. 享元模式的使用場景
在如下場景中則可以選擇使用享元模式。
● 系統中存在大量的相似物件。
● 細粒度的物件都具備較接近的外部狀態,而且內部狀態與環境無關,也就是說物件沒有特定身份。
● 需要緩衝池的場景。
6. 享元模式的執行緒安全問題:
由於使用的是共享物件,所以很可能會出現2個執行緒共用一個物件並且同時修改的問題,這樣就會出現執行緒安全問題。為了儘可能避免這個問題,要儘量的加大物件池中物件的數量,並且對於外部狀態,最好可以使用多個字串的組合來確定key值(即物件池中,一個物件對應一個key值)