享元模式(FlyWeight),其含義是運用共享技術有效地支持大量細粒度的對象,即系統只使用少許的對象,而這些對象都相近,狀態變化很小,對象使用次數卻不少。java
享元模式能作到共享的關鍵是區份內蘊狀態和外蘊狀態,一個內蘊狀態是存儲在享元對象內部的,而且是不會隨環境改變而有所不一樣的。所以一個享元能夠具備內蘊狀態並能夠共享。一個外蘊狀態是隨環境改變而改變的、不能夠共享的狀態。享元對象的外蘊狀態必須由客戶端保存,並在享元對象被建立以後,在須要使用的時候再傳入到享元對象內部。外蘊狀態不能夠影響享元對象的內蘊對象。換句話說,它們是互相獨立的。ide
其適用性:測試
一個應用程序使用了大量的對象,this
徹底因爲使用大量的對象,形成很大的存儲開銷,spa
對象的大多數狀態均可變爲外部狀態,設計
若是刪除對象的外部狀態,那麼能夠用相對較少的共享對象取代不少組對象,code
應用程序不依賴於對象標識。因爲Flyweight對象能夠被共享,對於概念上明顯有別的對象,標識測試將返回真值。對象
結構以下:blog
享元模式在使用時分爲單純享元模式和複合享元模式兩種,單純享元模式中Flyweight都是可共享的,也是如今Flyweight實現的較多實例。如今先列出單純享元模式:繼承
Flyweight.java
package org.designpattern.structural.flyweight;
public
abstract
class Flyweight {
protected
Character
intrinsicState;
protected Flyweight(
Character
intrinsicState){
this.intrinsicState = intrinsicState;
};
public
abstract
void operation(String extrinsicState);
public
Character
getIntrinsicState(){
return
this.intrinsicState;
};
}
ConcreteFlyweight.java繼承了Flyweight,實現了一個operation方法,類略。Flyweight是經過工廠獲得的,下面是FlyweightFactory.java
package
org.designpattern.structural.flyweight;
import java.util.HashMap;
public
class FlyweightFactory {
private HashMap flyWeights;
public FlyweightFactory(){
flyWeights =
new HashMap();
}
public Flyweight getFlyweight(Character key){
if(
this.flyWeights.containsKey(key)){
System.out.println(key + " already created!");
return (Flyweight) flyWeights.get(key);
}
else{
Flyweight flyweight =
new ConcreteFlyweight(key);
flyWeights.put(key,flyweight);
return flyweight;
}
}
}
若是是單純享元模式,到這裏再加上客戶測試類就結束了。若是使用複合享元模式,複合元素的對象的狀態是會改變的,因此複合享元對象是不能共享的。須要再增長一個類UnsharedConcreteFlyeweight.java
public class UnsharedConcreteFlyweight extends Flyweight {
private HashMap<Character,Flyweight> unsharedFlyweights;
private Flyweight flyweight;
public UnsharedConcreteFlyweight(Character intrinsicState) {
super(intrinsicState);
this.unsharedFlyweights =
new HashMap(20);
}
public
void add(Character key,Flyweight flyweight){
this.unsharedFlyweights.put(key,flyweight);
}
@Override
public
void operation(String extrinsicState) {
System.out.println("extrinsicState:" + extrinsicState);
Iterator<Map.Entry<Character,Flyweight>> it = unsharedFlyweights.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Character,Flyweight> entry = it.next();
Flyweight fly = entry.getValue();
fly.operation(extrinsicState);
}
}
}
此時在FlyweighFactory.java中須要增長一個方法支持不可共享的Flyweight的調用:
public Flyweight getUnsharedFlyweight(String keys ){
UnsharedConcreteFlyweight unsharedConcreteFlyweight =
new UnsharedConcreteFlyweight(
null);
for(
int i=0;i<keys.length();i++){
Character character =
new Character(keys.charAt(i));
unsharedConcreteFlyweight.add(character,getFlyweight(character));
}
return unsharedConcreteFlyweight;
}
下面是客戶測試類:
package
org.designpattern.structural.flyweight;
public
class Main {
public
static
void main(String[] args) {
FlyweightFactory factory =
new FlyweightFactory();
Flyweight fly1 = factory.getFlyweight('a');
fly1.operation("First call!");
Flyweight fly2 = factory.getFlyweight('b');
fly2.operation("Second call!");
Flyweight fly3 = factory.getFlyweight('a');
fly3.operation("Third call!");
System.out.println(fly1 == fly3);
Flyweight unsharedFlyweight = factory.getUnsharedFlyweight("abcde");
unsharedFlyweight.operation("Forth call!");
}
}
享元模式的有效性很大程度上取決於在何種情景下使用它,其主要缺點是使系統設計變得更加複雜,將享元對象的狀態外部化,而讀取外部狀態使得運行時間稍微變長。咱們一般會把Flyweight工廠設計爲單例模式,其能夠和許多模式共同使用更有效。