# 享元模式
# 概念
享元模式是一种结构型设计模式,通过共享对象来减少内存占用和对象创建开销。其核心思想是将对象状态分为两类:
1.内部状态(Intrinsic):可共享的、不变的部分(如颜色),存储在享元对象内部。
2.外部状态(Extrinsic):不可共享的、变化的部分(如位置、半径),由客户端在调用时传递。
# 作用
1.减少重复对象的创建,显著降低内存消耗。
2.提升系统性能,尤其在对象初始化成本较高时效果明显。
3.适用于需要管理大量相似对象的场景,通过对象复用优化资源。
# 场景
1.系统需要创建大量相似对象(如游戏中的粒子系统、文档编辑器中的字符对象)。
2.对象的大部分状态可以外部化(即状态可分离为内部共享部分和外部变化部分)。
3.需要缓存或对象池的场景(如网络请求复用、图形渲染中的基础元素复用)。
# 举例
以下是享元模式的典型实现代码:
// 享元接口
interface Circle {
void draw(int x, int y, int radius);
}
// 具体享元类
class ConcreteCircle implements Circle {
private final String color; // 内部状态(共享)
public ConcreteCircle(String color) {
this.color = color;
}
@Override
public void draw(int x, int y, int radius) { // 外部状态作为参数
System.out.printf("Drawing %s circle at (%d,%d) with radius %d\n",
color, x, y, radius);
}
}
// 享元工厂
class CircleFactory {
private static final Map<String, Circle> circleMap = new HashMap<>();
public static Circle getCircle(String color) {
// 如果没有生成特定颜色的圆,则生成并保存,最后再返回
if (!circleMap.containsKey(color)) {
Circle newCircle = new ConcreteCircle(color);
circleMap.put(color, newCircle);
}
return circleMap.get(color);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
String[] colors = {"Red", "Blue", "Green"};
// 获取10个圆形,但实际只创建3个对象
for(int i=0; i<10; i++){
String color = colors[i % 3];
Circle circle = CircleFactory.getCircle(color);
circle.draw(i*10, i*20, 5); // 外部状态每次不同
}
}
}
# 反例
未使用享元模式时,每次创建对象都会生成新实例,导致内存浪费:
// 未使用享元的简单圆形类
class SimpleCircle {
private String color;
public SimpleCircle(String color) {
this.color = color;
}
public void draw(int x, int y, int radius) {
System.out.printf("Drawing %s circle at (%d,%d) with radius %d\n",
color, x, y, radius);
}
}
// 客户端使用(每次创建新对象)
public class Client {
public static void main(String[] args) {
String[] colors = {"Red", "Blue", "Green"};
// 每次都会创建新对象(共创建10个对象)
for(int i=0; i<10; i++){
String color = colors[i % 3];
SimpleCircle circle = new SimpleCircle(color); // 每次都新建对象
circle.draw(i*10, i*20, 5);
}
}
}
# 原理
享元模式的核心是通过对象复用,将对象数量从“使用次数级别”降低到“不同内部状态组合级别”。例如,上述例子中10次调用仅创建3个对象(对应3种颜色),而非10个。其本质是区分对象的固有属性(内部状态)和运行时可变属性(外部状态),通过工厂模式管理共享对象的生命周期。
# 缺点
1.增加系统复杂性:需明确区分内部状态和外部状态,设计难度提升。
2.状态管理要求高:需确保内部状态真正不可变,外部状态正确传递,否则可能引发逻辑错误。
3.线程安全问题:共享对象在多线程环境下需额外同步机制,否则可能引发并发问题。
总结
享元模式通过共享对象优化内存使用,适用于大量相似对象的场景。其关键在于正确区分内部状态(共享)和外部状态(动态传递),并通过工厂模式管理共享实例。实际开发中,Java的String常量池、Integer.valueOf()缓存(-128~127)均为享元模式的经典应用。

微信公众号

QQ交流群
如若发现错误,诚心感谢反馈。
愿你倾心相念,愿你学有所成。
愿你朝华相顾,愿你前程似锦。