GOF设计模式——Flyweight模式
一、什么是Flyweight模式
Flyweight,是轻量级的意思,Flyweight模式旨在使得类的创建、使用变得简便。如何实现呢?在一般的编程里面,想要使用一个对象,会通过new的方式创建,那么每一个地方需要使用该对象,就要new一次,在计算机内存中则需要每次都要分配内存空间出来,当使用new的次数增多时,内存空间也随着消耗加大。Flyweight模式则是通过尽量共享实例来避免内存的大量消耗。
二、Flyweight模式的原理
Flyweight类:是一些需要被共享的类;
FlyweightFactory类:负责生成Flyweight类的工厂类;
Client类:调用类。
三、Flyweight模式实例
现在由一些由许多普通字符组合成为“大型字符”的类,它的实例就是重实例。示例中根据传递的数字,输出对应的文件内容。进行示例之前,要准备一些txt文件。
本示例的txt文件内容如下:
UML图:
1、BigChar类
package com.cjs.Flyweight;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BigChar {
private final String PATH = "E:\\IntelliJ Idea\\designMode\\src\\main\\resources\\";
private char charName;
private String fontdata;
public BigChar(char charName) {
this.charName = charName;
try {
BufferedReader reader = new BufferedReader(new FileReader(PATH+"big" + charName + ".txt"));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
buffer.append("\n");
}
reader.close();
this.fontdata = buffer.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void print() {
System.out.println(fontdata);
}
}
BigChar类定义了三个属性,PATH定义了文件路径,charName表示将要传进来的字符,如‘1’,‘2’等等,fontdata用于存储文件内容,以及输出。构造方法的作用是:根据传进来的字符,找到对应的txt文件,然后逐行读取信息,将信息用StringBuffer对象保存,最后一次性保存在fontdata字符串中。
2、BigCharFactory类
package com.cjs.Flyweight;
import java.util.HashMap;
public class BigCharFactory {
private HashMap pool = new HashMap();
private static BigCharFactory singleton = new BigCharFactory();//使用静态实现单例模式
private BigCharFactory() {
}
public static BigCharFactory getInstance() {
return singleton;
}
public synchronized BigChar getBigChar(char charName) {
BigChar bigChar = (BigChar) pool.get("" + charName);
if (bigChar == null) {
bigChar = new BigChar(charName);
pool.put("" + charName, bigChar);
}
return bigChar;
}
}
因为BigCharFactory对象是共享的,只需要一个,所以使用了单例模式,另外,该工厂类主要用于生产BigChar对象,所以定义了getBigChar方法,该方法作用是,先根据字符到pool里面找,是否存在对应的对象,如果存在,直接返回、使用BigChar对象,如果不存在,创建一个新的BigChar对象,并放在pool里面。pool是一个HashMap类型属性,使用键值对来管理BigChar对象。
3、BigString类
package com.cjs.Flyweight;
public 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();
}
}
}
BigString作用是根据传入的字符串,将其拆分为单个字符,通过字符获取对应的BigChar实例对象,逐个输出。
4、Main类
package com.cjs.Flyweight;
public class Main {
public static void main(String[] args) {
BigString bigString = new BigString("12323");
bigString.print();
}
}
输出结果:
四、总结
Flyweight模式核心在FlyweightFactory类的getFlyweight()方法的算法,什么时候创建新对象,如何创建。值得注意的是,Flyweight模式思想是“共享”,换句话说,同一个实例对象,会被多个地方使用,当要改变被共享的对象时,就会有多个地方产生影响。