享元模式(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工厂设计为单例模式,其能够和许多模式共同使用更有效。