第95章(1 / 1)

大话设计模式 吴强 1361 字 2个月前

大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