第一篇 生成及初始化对象 第七章 - 享元模式
我们曾提到“对象多样性”的概念,这里以“琵琶曲”为例继续讨论这一话题。
琵琶音域宽广,简单起见,假设它有4根弦,每根弦有25个发音点位,共可发出 4×25=100 种音。下面使用“音”类描述琵琶的声音。
// 音
public class Yin {
private int xian;// 1~4,4个弦号。
private int dian;// 1~25,25个点位。
public Yin(int xian, int dian) {
this.xian = xian;
this.dian = dian;
}
public void play() {
// 大弦嘈嘈如急雨,小弦切切如私语。
}
}
为了模拟琵琶的所有声音,我们需要100个对象,它们是:Yin(1,1),Yin(1,2),...,Yin(1,25),...,Yin(4,24),Yin(4,25)。对象多样性之“多”由此可见一斑。
生成太多的对象难免有浪费之嫌,毕竟内存空间向来宝贵。修改一下“音”类。
// 音
public class Yin {
private int xian;// 1~4,4个弦号。
private int dian;// 1~25,25个点位。
public Yin(int xian) {
this.xian = xian;
}
public void setDian(int dian) {
this.dian = dian;
}
public void play() {}
}
// 测试类
public class Test {
public void test() {
Yin obj = new Yin(1);// 生成对象并初始化弦号
obj.setDian(6);// 设置点位
obj.play();
obj.setDian(9);// 弦号不变,点位随机变化。
obj.play();
}
}
此时,我们仅需要4个对象,它们是:Yin(1),Yin(2),Yin(3),Yin(4)。这4个对象分别代表了琵琶的4根弦,模拟声音时,各对象中的弦号保持不变,发音点位随机变化。
这种有部分成员变量(如弦号)被共享使用的对象称为“享元对象”。使用享元对象可以降低生成的对象数量。
实践中常将享元对象放到“对象池”中缓存起来以备复用。来看例子。
// 享元对象工厂类
public class YinFactory {
// 对象池
private static Map<Integer, Yin> POOL = new HashMap<>();
public static Yin getYin(Integer i) {
Yin obj = null;
if (POOL.containsKey(i)) {
obj = POOL.get(i);
} else {
obj = new Yin(i);
POOL.put(i, obj);
}
return obj;
}
}
// 测试类
public class Test {
public void test() {
Yin obj = YinFactory.getYin(1);// 获取某弦号的对象
obj.setDian(6);// 设置点位
obj.play();
obj.setDian(9);// 点位随机变化
obj.play();
}
}
浙公网安备 33010602011771号