享元模式
1. 介绍
1.1 描述和作用
- 享元漠式(Flyweight Pattern)用共享技术有效地支持大量细粒度的对象
- “享”表示共享,“元”表示对象
- 常用于系统底层开发,解决系统的性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接对象中有我们需要的则直接拿来用,避免重新创建,如果没有我们需要的,则创建一个
- 享元模式能够解决重复对象的内存浪费的问题, 当系统中有大量相似对象,需要缓冲池时。不需要总是创建新对象,可以从缓冲池里拿。这样可以降低系统内存,同时提高效率
1.2 内部状态和外部状态
-
内部状态:
指对象共享出来的信息,存储在向原对象内部,且不会随环境改变
-
外部状态:
指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
现实举例:
下围棋时,棋盘上有很多的棋子,但是只有黑棋和白棋两种颜色。一盘围棋中可能有一白多个黑棋和白棋,这些黑棋或白棋的颜色是可以共享的,而棋子的位置是频繁改变而不可共享的。我们可以使用享元模式,使得棋盘上的棋子只有两个对象:黑棋对象和白棋对象。共享颜色,不共享坐标。
享元模式提高了系统的复杂性,需要分理处对象的内部状态和外部状态,而外部状态不应该随着内部状态的改变而改变
2. 原理和角色
- FlyWeight:是抽象的享元角色,是产品的抽象类。定义了对象的外部状态和内部状态的接口或实现
- ConcreteFlyWeight:是具体的享元角色,是具体的产品类。实现了抽象角色定义的相关业务
- UnSharedConcreteFlyWeight:是不可共享的角色,一般不会出现在享元工厂中
- FlyWeightFactory:享元工厂类,内部提供一个池容器,同时提供从池中存取数据的操作
3. 应用
享元模式经典的应用场景就是池技术了,string常量池、数据库连接池、缓冲池等等都是享元模式的应用,享元模式是池技术的重要实现方式
3.1 Integer源码应用分析
Integer的valueOf方法:如果参数在-128到127之间,则使用享元模式返回对象
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= Integer.high) {
// cache是缓存的常量池
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}