书城计算机大话设计模式
11030400000095

第95章 10 Flyweight模式在XML等数据源中应用

大B:“我们前面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用Flyweight模式可以提高效率,以唱片CD为例,在一个XML文件中,存放了多个CD的资料。”

每个CD有三个字段:

1、出片日期(year)

2、歌唱者姓名等信息(artist)

3、唱片曲目(title)

其中,歌唱者姓名有可能重复,也就是说,可能有同一个演唱者的多个不同时期不同曲目的CD。我们将‘歌唱者姓名’作为可共享的ConcreteFlyweight。其他两个字段作为UnsharedConcreteFlyweight。

首先看看数据源XML文件的内容:

《xml version=“1.0”?》

《collection》

《cd》

《title》Another Green World《/title》

《year》1978《/year》

《artist》Eno,Brian《/artist》

《/cd》

《cd》

《title》Greatest Hits《/title》

《year》1950《/year》

《artist》Holiday,Billie《/artist》

《/cd》

《cd》

《title》Taking Tiger Mountain(by strategy)《/title》

《year》1977《/year》

《artist》Eno,Brian《/artist》

《/cd》

……

《/collection》

虽然上面举例CD只有3张,CD可看成是大量重复的小类,因为其中成份只有三个字段,而且有重复的(歌唱者姓名)。

CD就是类似上面接口Flyweight:

public class CD{

private String title;

private int year;

private Artist artist;

public String getTitle(){return title;}

public int getYear(){return year;}

public Artist getArtist(){return artist;}

public void setTitle(String t){title=t;}

public void setYear(int y){year=y;}

public void setArtist(Artist a){artist=a;}

}

将“歌唱者姓名”作为可共享的ConcreteFlyweight:

public class Artist{

//内部状态

private String name;

//note that Artist is immutable。

String getName(){return name;}

Artist(String n){

name=n;

}

}

再看看Flyweight factory,专门用来制造上面的可共享的ConcreteFlyweight:Artist

public class ArtistFactory{

Hashtable pool=new Hashtable();

Artist getArtist(String key){

Artist result;

result=(Artist)pool。get(key);

////产生新的。

if(result……null){

result=new Artist(key);

pool。put(key,result);

}

return result;

}

}

当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大。

给个例子,coffee商店

package FlyWeight。coffeeshop;

public class Table{

private int number;

public int getNumber(){

return number;

}

public void setNumber(int number){

this。number=number;

}

public Table(int number){

super();

//TODO Auto-generated constructor stub

this。number=number;

}

}

package FlyWeight。coffeeshop;

public abstract class Order{?

public abstract void serve(Table table);

public abstract String getFlavor();

}

package FlyWeight。coffeeshop;

public class Flavor extends Order{

private String flavor;

public Flavor(String flavor){

super();

//TODO Auto-generated constructor stub

this。flavor=flavor;

}

public String getFlavor(){

return flavor;

}

public void setFlavor(String flavor){

this。flavor=flavor;

}

public void serve(Table table){

System。out。println(“Serving table” table。getNumber() “with flavor” flavor);

}

}

package FlyWeight。coffeeshop;

public class FlavorFactory{

private Order[]flavors=new Flavor[10];

private int ordersMade=0;//已经处理好的订单数

private int totalFlavors=0;//已购买的coffee风味种类数

public Order getOrder(String flavorToGet){

if(ordersMade>;0){

for(int i=0;i<ordersmade;i ){

if(flavorToGet。equalsIgnoreCase(flavors[i]。getFlavor()))

return flavors[i];

}

}

flavors[ordersMade]=new Flavor(flavorToGet);

totalFlavors ;

return flavors[ordersMade ];

}

public int getTotalFlavorsMade(){

return totalFlavors;

}

}

package FlyWeight。coffeeshop;

public class Client{

private static Order[]flavors=new Flavor[100];

private static int ordersMade=0;

private static FlavorFactory flavorFactory;

private static void takeOrders(String aFlavor){

flavors[ordersMade ]=flavorFactory。getOrder(aFlavor);

}

public static void main(String[]args){

flavorFactory=new FlavorFactory();

takeOrders(“Black Coffee”);

takeOrders(“Capucino”);

takeOrders(“Espresso”);

takeOrders(“Espresso”);

takeOrders(“Capucino”);

takeOrders(“Capucino”);

takeOrders(“Black Coffee”);

takeOrders(“Espresso”);

takeOrders(“Capucino”);

takeOrders(“Black Coffee”);

takeOrders(“Espresso”)。

for(int i=0;i<ordersmade;i ){

flavors[i]。serve(new Table(i));

}

System。out。println(\nTotal Flavor objrcts made:

flavorFactory。getTotalFlavorsMade());

}

}

//――

运行结果:

Serving table 0 with flavor Black Coffee

Serving table 1 with flavor Capucino

Serving table 2 with flavor Espresso

Serving table 3 with flavor Espresso

Serving table 4 with flavor Capucino

Serving table 5 with flavor Capucino

Serving table 6 with flavor Black Coffee

Serving table 7 with flavor Espresso

Serving table 8 with flavor Capucino

Serving table 9 with flavor Black Coffee

Serving table 10 with flavor Espresso

</ordersmade;i ){

</ordersmade;i ){