享元模式是通过共享来有效地支持大量细粒度对象。这种模式通过共享来最小化内存使用或计算开销,适用于需要创建大量相似对象的场景。
// 享元类(字符属性)
class CharacterStyle {
constructor(font, size, color) {
this.font = font;
this.size = size;
this.color = color;
}
render(char) {
console.log(`Rendering '${char}' in ${this.font} ${this.size}px ${this.color}`);
}
}
// 享元工厂
class CharacterStyleFactory {
static #styles = new Map();
static getStyle(font, size, color) {
const key = `${font}-${size}-${color}`;
if (!this.#styles.has(key)) {
this.#styles.set(key, new CharacterStyle(font, size, color));
}
return this.#styles.get(key);
}
static get stylesCount() {
return this.#styles.size;
}
}
// 上下文类(具体字符)
class Character {
#char;
#style;
#x;
#y;
constructor(char, x, y, font, size, color) {
this.#char = char;
this.#x = x;
this.#y = y;
this.#style = CharacterStyleFactory.getStyle(font, size, color);
}
render() {
console.log(`Character at (${this.#x}, ${this.#y}):`);
this.#style.render(this.#char);
}
}
// 文本编辑器类
class TextEditor {
#characters = [];
addCharacter(char, x, y, font, size, color) {
this.#characters.push(new Character(char, x, y, font, size, color));
}
render() {
this.#characters.forEach(char => char.render());
}
}
// 使用示例
function demonstrateFlyweight() {
const editor = new TextEditor();
// 添加一些字符
editor.addCharacter('H', 0, 0, 'Arial', 12, 'black');
editor.addCharacter('e', 10, 0, 'Arial', 12, 'black');
editor.addCharacter('l', 20, 0, 'Arial', 12, 'black');
editor.addCharacter('l', 30, 0, 'Arial', 12, 'black');
editor.addCharacter('o', 40, 0, 'Arial', 12, 'black');
editor.addCharacter('W', 60, 0, 'Times New Roman', 14, 'red');
editor.addCharacter('o', 80, 0, 'Times New Roman', 14, 'red');
editor.addCharacter('r', 90, 0, 'Times New Roman', 14, 'red');
editor.addCharacter('l', 100, 0, 'Times New Roman', 14, 'red');
editor.addCharacter('d', 110, 0, 'Times New Roman', 14, 'red');
// 渲染所有字符
editor.render();
// 显示创建的样式数量
console.log(`\nTotal number of character styles created: ${CharacterStyleFactory.stylesCount}`);
}
demonstrateFlyweight();
实现思路
-
CharacterStyle类(享元):- 包含字符的内在状态(字体、大小、颜色)。
- 提供
render方法来渲染字符。
-
CharacterStyleFactory类(享元工厂):- 使用静态私有字段
#styles来存储已创建的样式。 - 提供
getStyle方法来获取或创建样式,确保相同的样式只被创建一次。 - 提供
stylesCountgetter 来获取创建的样式数量。
- 使用静态私有字段
-
Character类(上下文):- 包含字符的外在状态(字符值、位置)。
- 引用一个
CharacterStyle对象来渲染字符。
-
TextEditor类:- 管理多个
Character对象。 - 提供方法来添加字符和渲染整个文本。
- 管理多个
优点
- 内存优化:通过共享
CharacterStyle对象,大大减少了内存使用。 - 性能提升:减少了对象创建的次数,可能提高性能。
- 透明性:客户端代码不需要知道享元模式的存在。
- 可扩展性:可以轻松添加新的字符样式而不影响现有代码。