一个内蕴状态是存储在享元对象内部的,并且是不会随改变而有所不同的,因此,一个享元可以具有内蕴状态并可以共享。
一个外蕴状态时随着环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴状态。换句话说,它们是相互独立的。
享元模式的种类:根据所涉及的享元对象的内部表象,享元模式可以分成单纯享元模式和复合享元模式两种形式。
在Java语言中,String类型就使用了享元模式,String对象是不变对象,一旦创建出来就不能改变。如果需要改变一个字符串的值,就只好创建一个新的String对象。在JVM内部,String对象都是共享的,如果一个系统中有两个String对象所包含的字符串相同的话,JVM实际上只创建一个String对象提供给两个引用,从而实现String对象的共享。String的intern()方法给出这个字符串在共享池中的唯一实例。
单纯享元模式的结构:
抽象享元角色FlyWeight
public abstract class CD {
private CDInfo cdinfo;
private Artist artist;
public abstract void operation(Artist artist,CDInfo cdinfo);
public CD(CDInfo cdinfo,Artist artist){
this.cdinfo=cdinfo;
this.artist=artist;
}
....set,get方法省略
}
//外部状态
public class CDInfo {
private String title;
...其它属性和set,get方法省略
}
//内部状态
public class Artist {
private String name;
...其它属性和set,get方法省略
}
享元工厂FlyWeightFactory
public class ArtistFactory {
Hashtable pool = new Hashtable();
Artist getArtist(String key){
Artist result;
result = (Artist)pool.get(key);
产生新的Artist
if(result == null) {
result = new Artist(key);
pool.put(key,result);
}
return result;
}
}
具体享元角色ConcreteFlyWeight
public class RealCD extends CD{
public RealCD(CDInfo cdinfo,Artist artist){
super(cdinfo,artist);
}
public void operation(Artist artist,CDInfo cdinfo){
System.out.println(artist.getName()+"创建专辑:"+ cdinfo.getTitle());
}
}
public class Cilent {
public static void main(String[] agrs){
CDInfo cdinfo1 =new CDInfo("天堂");
CDInfo cdinfo2 =new CDInfo("地狱");
ArtistFactory factory = new ArtistFactory();
Artist artist1=factory.getArtist("mike");
CD cd1 = new RealCD(cdinfo1,artist1);
CD cd2 = new RealCD(cdinfo2,artist1);
cd1.operation(artist1,cdinfo1);
cd2.operation(artist1,cdinfo2);
}
}
mike 在天堂地狱专辑得到享元。