📄 s_flyweight.java
字号:
/*
FLYWEIGHT—每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
*/
import java.io.*;
import java.util.*;
public class S_Flyweight {
public static void main(String[] args) {
BigString bs = new BigString("145651");
bs.print();
}
}
class BigString {
// 「大型文字」的数组
private BigChar[] bigchars;
// 构造子
public BigString(String string) {
bigchars = new BigChar[string.length()];
BigCharFactory factory = BigCharFactory.getInstance();
for (int i = 0; i < bigchars.length; i++) {
bigchars[i] = factory.getBigChar(string.charAt(i));
}
}
// 显示
public void print() {
for (int i = 0; i < bigchars.length; i++) {
bigchars[i].print();
}
}
}
class BigCharFactory {
// 管理现有的BigChar的对象实例
private Hashtable pool = new Hashtable();
// Singleton Pattern
private static BigCharFactory singleton = new BigCharFactory();
// 构造子
private BigCharFactory() {
}
// 取得唯一的对象实例
public static BigCharFactory getInstance() {
return singleton;
}
// 产生(共享)BigChar的对象实例
public synchronized BigChar getBigChar(char charname) {
BigChar bc = (BigChar)pool.get("" + charname);
if (bc == null) {
bc = new BigChar(charname); // 在此产生BigChar的对象实例
pool.put("" + charname, bc);
}
return bc;
}
}
class BigChar {
// 字符名称
private char charname;
// 输出成大型文字的字串(有'#' '.' '\n'的行)
private String fontdata;
// 构造子
public BigChar(char charname) {
this.charname = charname;
try {
BufferedReader reader = new BufferedReader(
new FileReader("bigchar/big" + charname + ".txt")
);
String line;
StringBuffer buf = new StringBuffer();
while ((line = reader.readLine()) != null) {
buf.append(line);
buf.append("\n");
}
reader.close();
this.fontdata = buf.toString();
} catch (IOException e) {
this.fontdata = charname + "?";
}
}
// 输出大型文字
public void print() {
System.out.print(fontdata);
}
}
/*
Flyweight模式在XML等数据源中应用
我们上面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用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);
////产生新的Artist
if(result == null) {
result = new Artist(key);
pool.put(key,result);
}
return result;
}
}
当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -