五、享元模式(Flyweight)
享元模式简介
Flyweight本意是拳击中的绳量级,在这里是指代共享的元素。
享元模式指多个元素共享使用。把生活中的公共设施比作这里的元素,每个人都能享用元素,人人共享资源。享元模式最大的特点就是资源共享性。
Java中String类型利用了享元模式。代码如下:
String a = "abc";
String b = "abc";
System.out.println(a == b);
打印结果:true。
分析:”abc”本质上是字符串常量,存储在常量池中,常量池位于方法区(Method Area)区中,什么是常量池?
常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法和名称和描述符
Java虚拟机收到创建字符串常量”abc”的命令后,首先会检查方法区中的常量池是否含有”abc”字符串,检查完毕,没有,于是创建字符串常量”abc”,然后赋值给a引用变量,至此a就有了”abc”的引用。b引用变量创建时,Java虚拟机检查字符串常量是否有”abc”,有,直接将现成的”abc”赋值给b变量,b也有了”abc”的引用。由于”abc”在方法区中的内存地址是固定的,因此a、b引用的是同一个内存地址值,a == b,当然返回true。
这就是一个典型的享元模式架构。
享元模式结构
- 元素仓库类(FlyweightWarehouse)
- 元素类(Flyweight)
元素类是就是指一类元素,这类元素可以是任意类型的。
元素仓库类是用来存储若干个元素的,一般情况下以Hashtable双列集合封装,key为元素的标识,value为元素类实例。元素仓库类为了保证元素共享,其封装若干元素的集合类的成员变量必须用static修饰,变量初始化使用static代码块。元素仓库类最基本的功能就是供给共享的元素,这也是享元模式的精髓所在。
代码:
import java.util.HashMap;
import java.util.Map;
/**
* @author Hanlin Wang
*/
public class FlyweightMode {
public static void main(String[] args) {
Flyweight ele = FlyweightWareHouse.getFlyweight(1);
System.out.println(ele.getInfo());
}
}
//元仓库类
class FlyweightWareHouse{
//在类加载时就完成初始化
private static Map<Integer, Flyweight> flyweights = new HashMap<Integer, Flyweight>();
//flyweights初始化
static{
flyweights.put(1, new Flyweight("MySQL"));
flyweights.put(2, new Flyweight("Oracle"));
flyweights.put(3, new Flyweight("HBase"));
flyweights.put(4, new Flyweight("MongoDB"));
}
//得到元素的方法
public static Flyweight getFlyweight(int key){
return flyweights.get(key);
}
}
//元类
class Flyweight{
//元素类的信息
private String info;
//通过构造方法初始化info
public Flyweight(String info) {
this.info = info;
}
//info成员变量的getter、setter
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
解析:Flyweight为元素类,info为属性,info属性通过构造方法初始化,并带有getter、setter方法。FlyweightWarehouse为元素仓库,flyweights属性为Map类型,其key为标识,value为Flyweight的实例对象,必须以static修饰。FlyweightWarehouse提供了一个方法getFlyweight(int key),用于获取共享的元素。