大B:“我们前面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用Flyweight模式可以提高效率,以唱片CD为例,在一个XML文件中,存放了多个CD的资料。”
每个CD有三个字段:
1、出片日期(year)
2、歌唱者姓名等信息(artist)
3、唱片曲目(title)
其中,歌唱者姓名有可能重复,也就是说,可能有同一个演唱者的多个不同时期不同曲目的CD。我们将‘歌唱者姓名’作为可共享的ConcreteFlyweight。其他两个字段作为UnsharedConcreteFlyweight。
首先看看数据源XML文件的内容:
《xmlversion=“1.0”?》
《collection》
《cd》
《title》AnotherGreenWorld《/title》
《year》1978《/year》
《artist》Eno,Brian《/artist》
《/cd》
《cd》
《title》GreatestHits《/title》
《year》1950《/year》
《artist》Holiday,Billie《/artist》
《/cd》
《cd》
《title》TakingTigerMountain(bystrategy)《/title》
《year》1977《/year》
《artist》Eno,Brian《/artist》
《/cd》
……
《/collection》
虽然上面举例CD只有3张,CD可看成是大量重复的小类,因为其中成份只有三个字段,而且有重复的(歌唱者姓名)。
CD就是类似上面接口Flyweight:
publicclassCD{
privateStringtitle;
privateintyear;
privateArtistartist;
publicStringgetTitle(){returntitle;}
publicintgetYear(){returnyear;}
publicArtistgetArtist(){returnartist;}
publicvoidsetTitle(Stringt){title=t;}
publicvoidsetYear(inty){year=y;}
publicvoidsetArtist(Artista){artist=a;}
}
将“歌唱者姓名”作为可共享的ConcreteFlyweight:
publicclassArtist{
//内部状态
privateStringname;
//notethatArtistisimmutable.
StringgetName(){returnname;}
Artist(Stringn){
name=n;
}
}
再看看Flyweightfactory,专门用来制造上面的可共享的ConcreteFlyweight:Artist
publicclassArtistFactory{
Hashtablepool=newHashtable();
ArtistgetArtist(Stringkey){
Artistresult;
result=(Artist)pool.get(key);
////产生新的。
if(result……null){
result=newArtist(key);
pool.put(key,result);
}
returnresult;
}
}
当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大。
给个例子,coffee商店
packageFlyWeight.coffeeshop;
publicclassTable{
privateintnumber;
publicintgetNumber(){
returnnumber;
}
publicvoidsetNumber(intnumber){
this.number=number;
}
publicTable(intnumber){
super();
//TODOAuto-generatedconstructorstub
this.number=number;
}
}
packageFlyWeight.coffeeshop;
publicabstractclassOrder{?
publicabstractvoidserve(Tabletable);
publicabstractStringgetFlavor();
}
packageFlyWeight.coffeeshop;
publicclassFlavorextendsOrder{
privateStringflavor;
publicFlavor(Stringflavor){
super();
//TODOAuto-generatedconstructorstub
this.flavor=flavor;
}
publicStringgetFlavor(){
returnflavor;
}
publicvoidsetFlavor(Stringflavor){
this.flavor=flavor;
}
publicvoidserve(Tabletable){
System.out.println(“Servingtable”+table.getNumber()+“withflavor”+flavor);
}
}
packageFlyWeight.coffeeshop;
publicclassFlavorFactory{
privateOrder[]flavors=newFlavor[10];
privateintordersMade=0;//已经处理好的订单数
privateinttotalFlavors=0;//已购买的coffee风味种类数
publicOrdergetOrder(StringflavorToGet){
if(ordersMade>0){
for(inti=0;i