描述
- 通过共享对象,来减少重复对象的创建,节省系统资源的利用率。
结构
- 内部状态:不会随外部条件,客户端需求而改变的共享部分
- 外部状态:会随外部条件,客户端的需求,从而改变的私有部分
角色
- 抽象享元角色:存储内部状态(公共部分)。
- 具体享元角色:实现抽象享元角色,为享元类提供存储空间,一般可以设计为单例。
- 非享元角色:存储外部状态(私有部分)。
- 享元工厂角色:负责管理和创建享元角色。为客户提供享元角色(存在则提供,不存在则创建)。
例子
- 比如俄罗斯方块游戏,如果是取过的图形,则取出来使用,没有的图形,则创建
代码实现
public class Test {
public static void main(String[] args) {
GraphFactory factory = GraphFactory.getInstance();
AbstractGraph lGraph = factory.getGraphByName("L");
lGraph.show("左");
AbstractGraph zGraph = factory.getGraphByName("Z");
zGraph.show("上");
AbstractGraph zGraph2 = factory.getGraphByName("Z");
zGraph.show("下");
}
}
abstract class AbstractGraph {
public abstract String appearance();
public void show(String direction) {
System.out.println("落下:" + direction + this.appearance());
}
}
class LGraph extends AbstractGraph {
@Override
public String appearance() {
return "L形";
}
}
class ZGraph extends AbstractGraph {
@Override
public String appearance() {
return "Z形";
}
}
class GraphFactory {
private Map<String, AbstractGraph> data = new HashMap<>();
private static final GraphFactory graphFactory = new GraphFactory();
GraphFactory() {
data.put("L", new LGraph());
data.put("Z", new ZGraph());
}
public static GraphFactory getInstance() {
return graphFactory;
}
public AbstractGraph getGraphByName(String name) {
return data.get(name);
}
}
优点
- 相同对象不用重复创建,节省系统资源,提高性能。
- 外部状态(例子中的方向)相对独立,不影响内部状态(例子中的形状)。
缺点
使用场景
- 存在大量相同或相似的对象(可外部化),造成内存大量耗费时。
- 享元模式需要有享元池,享元池需要一定系统内存资源,因此多次重复使用时才值得使用享元模式。
JDK中的使用
- Integer类:-128 到 127 使用了享元模式(IntegerCache)。
- 第一次调用 Integer.valueOf(),会初始化cache[],缓存 -128 到 127到cache[]。
- 当 valueOf() 范围是在-128 到 127时,是从cache[]中取同一个对象。