享元模式通过共享相似或相同的对象来减少内存使用和提高性能. 核心思想是把对象的状态分为内部状态和外部状态, 其中内部状态可以共享, 外部状态则由客户端来负责. 通过共享内部状态可以减少需要创建的对象数量, 从而节约内存

享元模式结构

  • 享元接口: 定义对象的接口, 通过这个接口, 享元可以接收并作用于外部状态
  • 具体享元类: 实现享元接口, 并存储可以共享的内部状态
  • 非共享享元类: 不需要共享的享元接口子类. 因为享元接口共享了具体的享元对象, 因此可以不需要
  • 享元工厂: 用于管理和创建享元对象

享元模式实现

假设我们有一个需要绘制许多字符的文本编辑器, 每个字符都有特定的样式(例如字体、大小、颜色等). 如果为每个字符都创建一个对象, 这将导致大量的内存消耗. 我们可以使用享元模式来共享相同样式的字符对象, 从而减少内存使用

import java.util.HashMap;
import java.util.Map;

// 享元接口
interface Character {
void display(int x, int y);
}

// 具体享元类
class ConcreteCharacter implements Character {
private char symbol;

public ConcreteCharacter(char symbol) {
this.symbol = symbol;
}

@Override
public void display(int x, int y) {
System.out.println("Character: " + symbol + " at (" + x + ", " + y + ")");
}
}

// 享元工厂
class CharacterFactory {
private Map<Character, Character> characters = new HashMap<>();

public Character getCharacter(char symbol) {
Character character = characters.get(symbol);
if (character == null) {
character = new ConcreteCharacter(symbol);
characters.put(symbol, character);
}
return character;
}
}

// 客户端
public class Client {
public static void main(String[] args) {
CharacterFactory factory = new CharacterFactory();

String document = "AABBCC";
int x = 0;
int y = 0;

for (char c : document.toCharArray()) {
Character character = factory.getCharacter(c);
character.display(x, y);
x += 10;
}
}
}

优点:

  • 减少内存使用. 通过共享相同或相似的对象, 可以减少内存消耗
  • 提高系统性能: 减少了对象的创建和销毁, 提高系统性能

缺点:

  • 复杂性增加: 需要引入额外的代码来管理共享对象和区分内部状态和外部状态, 增加系统复杂性
  • 可能导致线程安全问题: 由于享元对象是共享的, 在多线程环境下需要考虑线程安全问题