FlyWeight是”轻量级“的意思,指的是拳击比赛中选手体重最轻的等级。顾名思义,该设计模式的作用是为了让对象变”轻“。
对象在计算机中是虚拟存在的东西,它的”重“和”轻“并非指实际的重量,而是它们”所使用的内存大小“,使用内存多的就是”重对象“,使用内存少的就是”轻“对象。
在Java中,可以通过以下语句生成Something类的实例。 new Something()
为了能够在计算机中保存该对象那个,需要分配给其足够的内存空间,当程序中需要大量对象的时候,如果都使用new关键字来分配内存,将会消耗大量内存空间。
关于FlyWeight模式,就是”通过尽量共享实例来避免new出实例“。
2、示例程序在示例程序中,有一个将普通字符组合成”大型字符“的类,它的实例就是重实例,如下图:以文本形式保存了大型字符‘0’~‘9’的字体数据。
下表展示了该示例程序中所使用的类:
BigCharFactory 表示生成和共用BigChar类的实例的类BigChar 表示大型字符的类BigString 表示多个BigChar组成的“大型字符串”的类main 测试程序行为的类
BigChar类是表示大型字符的类,需要将其保存在内存中,然后使用print方法输出大型字符。大型字符会消耗大量的内存,因此我们要去考虑如何共享BigChar类的实例。
BigCharFatory类会根据需要生成BigChar类的实例,不过如果发现之前已经生成了某个大型字符的BigChar类的实例,则会直接利用该实例,而不会在生成新实例。生成的实例全部会保存在cache字段中。此外
为了能够快速查找之前是否已经生成某个大型字符所对应的实例,我们使用了HashMap类。
BigString类是用于多个BigChar组成的“大型字符串”。
Main类是用于测试程序行为的类。
下图表示示例程序的类图:
BigChar.java
package main.flyweight.bigchar;
import java.util.HashMap;
public class BigChar {
public char charName;
public String value;
BigChar(char charName) {
this.charName = charName;
this.value = map.get("" + charName);
}
public void print() {
System.out.println(value);
}
public static HashMap map = new HashMap<>();
static {
map.put("0", "....######......n" +
"..##......##....n" +
"..##......##....n" +
"..##......##....n" +
"..##......##....n" +
"..##......##....n" +
"....######......n" +
"................");
map.put("1", "......##........n" +
"..######........n" +
"......##........n" +
"......##........n" +
"......##........n" +
"......##........n" +
"..##########....n" +
"................n");
map.put("2", "....######......n" +
"..##......##....n" +
"..........##....n" +
"......####......n" +
"....##..........n" +
"..##............n" +
"..##########....n" +
"................n");
map.put("3", "....######......n" +
"..##......##....n" +
"..........##....n" +
"......####......n" +
"..........##....n" +
"..##......##....n" +
"....######......n" +
"................n");
map.put("4", "........##......n" +
"......####......n" +
"....##..##......n" +
"..##....##......n" +
"..##########....n" +
"........##......n" +
"......######....n" +
"................n");
map.put("5", "..##########....n" +
"..##............n" +
"..##............n" +
"..########......n" +
"..........##....n" +
"..##......##....n" +
"....######......n" +
"................n");
map.put("6", "....######......n" +
"..##......##....n" +
"..##............n" +
"..########......n" +
"..##......##....n" +
"..##......##....n" +
"....######......n" +
"................n");
map.put("7", "..##########....n" +
"..##......##....n" +
"..........##....n" +
"........##......n" +
"......##........n" +
"......##........n" +
"......##........n" +
"................n");
map.put("8", "....######......n" +
"..##......##....n" +
"..##......##....n" +
"....######......n" +
"..##......##....n" +
"..##......##....n" +
"....######......n" +
"................n");
map.put("9", "....######......n" +
"..##......##....n" +
"..##......##....n" +
"....########....n" +
"..........##....n" +
"..##......##....n" +
"....######......n" +
"................n");
}
}
BigCharFactory.java
package main.flyweight.bigchar;
import java.util.HashMap;
public class BigCharFactory {
private volatile HashMap cache = new HashMap<>();
private static BigCharFactory Singleton = new BigCharFactory();
private BigCharFactory() {
}
public static BigCharFactory getBigCharFactory() {
return Singleton;
}
public BigChar getBigChar(char value) {
if (cache.containsKey("" + value)) {
return cache.get("" + value);
} else {
synchronized (Singleton) {
if (cache.containsKey("" + value)) {
return cache.get("" + value);
} else {
BigChar bigChar = new BigChar(value);
cache.put("" + value, bigChar);
return bigChar;
}
}
}
}
}
BigString.java
package main.flyweight;
import main.flyweight.bigchar.BigChar;
import main.flyweight.bigchar.BigCharFactory;
public class BigString {
public String value;
private BigChar[] detail;
public BigString(String value) {
this.value = value;
this.detail = new BigChar[value.length()];
BigCharFactory factory = BigCharFactory.getBigCharFactory();
for (int i = 0; i < value.length(); i++) {
this.detail[i] = factory.getBigChar(value.charAt(i));
}
}
public void print(){
for (int i = 0; i < detail.length; i++) {
detail[i].print();
}
}
}
main.java
package main.flyweight;
public class Main {
public static void main(String[] args) {
BigString bigString1 = new BigString("117643");
bigString1.print();
System.out.println();
BigString bigString2 = new BigString("5200");
bigString2.print();
System.out.println();
BigString bigString3 = new BigString("52000");
bigString3.print();
System.out.println();
BigString bigString = new BigString("2500");
}
}
字符串“1212123”对应的BigString类实例的样子:
FlyWeight(轻量级):按照通常方式编写程序会导致程序变重,所以如果能够共享实例会比较耗,而FlyWeight角色表示的就是那些实例会被共享的类,在示例程序中,由BigChar类来扮演此角色。
FlyWeightFactory(轻量级工厂):FlyWeightFactory角色是生成FlyWeight角色的工厂。在工厂中生成FlyWeight角色可以实现共享实例。在示例程序中,由BigCharFactory类扮演此角色。
Client(请求者):Client角色使用FlyWeightFactory角色来生成FlyWeight角色。在示例程序中,由BigString来扮演此角色。
4、拓展FlyWeight模式的主题是“共享”,那么在共享实例的时候应当注意什么?
区分Intrinsic State信息和Extrinsic State信息
应该共享的信息被称作Intrinsic信息,Intrinsic 的意思是“本质的、固有的”。在我们示例的程序中,BigChar的字体数据不论在BigString中的哪个地方都不会改变。因此BigChar表示的信息就是Intrinsic信息。
不应该共享的信息被称作Extrinsic信息。Extrinsic的意思是“外在的,非本质的”。在示例程序中,BigChar的实例在BigString中的第几个字符这种信息会根据BigString重中的位置变化而变化,所以不应该在BigChar中保存这个信息,它属于Extrinsic信息。



