1. 设计模式之享元模式:简单的jvm内存对象池缓存
1.1. 介绍
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元可以理解为 享受 元数据;同一个数据,可以认为是一个元数据,整个系统里这个数据就一份,缓存起来。实际项目中,例如权限数据,读多写少,数据简单,就可以使用享元模式。
享元模式 vs 单例模式
对比维度 | 享元模式 | 单例模式 |
---|---|---|
目的 | 共享多个相似对象。 | 全局唯一实例。 |
对象数量 | 多个(按需共享)。 | 仅一个。 |
状态管理 | 分离内部状态和外部状态。 | 通常无状态或全局状态。 |
应用场景
游戏开发:大量重复的游戏对象(如子弹、NPC、粒子效果)。
图形渲染:文本编辑器中的字符、表格单元格样式。
数据库连接池:复用连接对象而非频繁创建。
线程池/对象池:复用线程或资源密集型对象。
优缺点及建议
优点
1.显著减少内存占用。
2.提升性能(减少对象创建开销)。
3.适合高频使用的轻量级对象。
缺点
1.增加代码复杂度(需分离内外状态)。
2.共享对象可能导致线程安全问题。
使用建议
1.在创建大量相似对象时考虑使用享元模式。
2.确保享元对象的内部状态是共享的,而外部状态是独立于对象的。
注意事项
1.使用工厂类集中管理共享对象(如`Map`缓存)。
2.确保内部状态是 不可变 的(避免共享冲突)。
3.外部状态应尽量简单(如坐标、颜色)。
1.2. 实现及相关代码
假设有一个业务,缓存某数据对象,同一份数据,只有一份。
1.2.1. 相关代码
接口及数据对象
public static interface Flyweight {
void execute();
String getName();
void setName(String name);
}
public static class ConcreteFlyweight implements Flyweight {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ConcreteFlyweight(String name) {
super();
this.name = name;
}
public void execute() {
System.out.println(name + "执行功能逻辑");
}
}
public static class FlyweightFactory {
private static Map<String, Flyweight> cachePool = new HashMap<String, Flyweight>();
public static Flyweight get(String name) {
Flyweight flyweight = cachePool.get(name);
if(flyweight == null) {
flyweight = new ConcreteFlyweight(name);
cachePool.put(name, flyweight);
}
return flyweight;
}
}
调用方法
public static void main(String[] args) {
Flyweight flyweight1 = FlyweightFactory.get("对象1");
flyweight1.execute();
Flyweight flyweight2 = FlyweightFactory.get("对象1");
flyweight2.execute();
System.out.println(flyweight1 == flyweight2);
}