享元模式
约 507 字
享元模式
核心思想
享元模式允许共享多个对象的相同状态,来在有限的内存中载入更多的对象。
典型用例
网络连接池
在需要大量建立相似的网络连接(如数据库连接)的情况下,通过共享连接对象来减少创建和销毁连接的开销。
在这个例子中,连接池管理着一组预先创建的数据库连接对象。当需要一个连接时,从池中获取一个可用的连接;当完成使用时,将连接返回给池。这种方式可以显著减少频繁创建和销毁连接的性能开销。
// npm run code src/code/design-pattern/flyweight/connection-pool.ts
export {};
// 网络连接接口
interface NetworkConnection {
open(): void;
close(): void;
}
// 网络连接的具体实现
class DatabaseConnection implements NetworkConnection {
open(): void {
console.log('Database Connection opened.');
}
close(): void {
console.log('Database Connection closed.');
}
}
// 创建一个连接池负责管理连接的对象
class ConnectionPool {
private availableConnections: NetworkConnection[] = [];
private inUseConnections: NetworkConnection[] = [];
constructor(private poolSize: number) {
for (let i = 0; i < this.poolSize; i++) {
this.availableConnections.push(new DatabaseConnection());
}
}
getConnection(): NetworkConnection {
if (this.availableConnections.length === 0) {
throw new Error('No available connections');
}
const connection = this.availableConnections.pop()!;
this.inUseConnections.push(connection);
connection.open();
return connection;
}
releaseConnection(connection: NetworkConnection): void {
const connectionIndex = this.inUseConnections.indexOf(connection);
if (connectionIndex !== -1) {
this.inUseConnections.splice(connectionIndex, 1);
this.availableConnections.push(connection);
connection.close();
}
}
}
const pool = new ConnectionPool(2); // 创建一个有两个连接的连接池
try {
const connection1 = pool.getConnection(); // 获取连接
// 使用连接...
pool.releaseConnection(connection1); // 释放连接
const connection2 = pool.getConnection(); // 再次获取连接
// 使用连接...
pool.releaseConnection(connection2); // 释放连接
} catch (error) {
console.error(error);
}
字符和字符串处理
在文本编辑器或处理文档的应用中,享元模式可以减少对象数量以降低程序内存的占用,适合用于处理大量相似对象的情况。
// npm run code src/code/design-pattern/flyweight/character-and-string-processing.ts
export {};
class CharacterFlyweight {
private readonly character: string;
constructor(character: string) {
this.character = character;
}
public print(): string {
return this.character;
}
}
class FlyweightFactory {
private characters: {[key: string]: CharacterFlyweight} = {};
public getCharacter(char: string): CharacterFlyweight {
if (!this.characters[char]) {
this.characters[char] = new CharacterFlyweight(char);
}
return this.characters[char];
}
}
class MyDocument {
private characters: CharacterFlyweight[] = [];
private factory: FlyweightFactory = new FlyweightFactory();
public addCharacter(char: string): void {
this.characters.push(this.factory.getCharacter(char));
}
public print(): string {
return this.characters.map(char => char.print()).join('');
}
}
const myDocument = new MyDocument();
const text = "Hello, flyweight pattern!";
for (const char of text) {
myDocument.addCharacter(char);
}
console.log(myDocument.print());
图形和游戏开发中的对象共享
在图形渲染或游戏开发中,享元模式可以共享相似对象,如树木、草、云等,这可以有效地管理大量重复的图形对象,节省内存,提供渲染效率。
// npm run code src/code/design-pattern/flyweight/object-sharing-in-game-development.ts
export {};
class GraphicFlyweight {
private readonly type: string;
constructor(type: string) {
this.type = type;
}
public render(x: number, y: number): string {
return `Rendering a ${this.type} at (${x}, ${y}).`;
}
}
class FlyweightFactory {
private graphics: {[key: string]: GraphicFlyweight} = {};
public getGraphic(type: string): GraphicFlyweight {
if (!this.graphics[type]) {
this.graphics[type] = new GraphicFlyweight(type);
}
return this.graphics[type];
}
}
class Scene {
private graphics: { graphic: GraphicFlyweight; x: number; y: number; }[] = [];
private factory: FlyweightFactory = new FlyweightFactory();
public addGraphic(type: string, x: number, y: number): void {
const graphic = this.factory.getGraphic(type);
this.graphics.push({ graphic, x, y });
}
public render(): void {
for (const { graphic, x, y } of this.graphics) {
console.log(graphic.render(x, y));
}
}
}
const scene = new Scene();
// 添加图形对象
scene.addGraphic("Tree", 1, 2);
scene.addGraphic("Cloud", 5, 3);
scene.addGraphic("Grass", 3, 4);
scene.addGraphic("Tree", 2, 6); // 会重用之前创建的 'Tree' 对象
// 渲染场景
scene.render();
用户界面组件
在用户界面设计中,享元模式可以有效地管理和重用相似的组件,例如按钮或图标,尤其是当这些组件在多个地方以相同或类似的形式出现时。
// npm run code src/code/design-pattern/flyweight/user-interface-component.ts
export {};
class ComponentFlyweight {
private readonly type: string;
constructor(type: string) {
this.type = type;
}
public render(position: string): string {
return `Rendering a ${this.type} at ${position}.`;
}
}
class FlyweightFactory {
private components: {[key: string]: ComponentFlyweight} = {};
public getComponent(type: string): ComponentFlyweight {
if (!this.components[type]) {
this.components[type] = new ComponentFlyweight(type);
}
return this.components[type];
}
}
class UI {
private components: { component: ComponentFlyweight; position: string; }[] = [];
private factory: FlyweightFactory = new FlyweightFactory();
public addComponent(type: string, position: string): void {
const component = this.factory.getComponent(type);
this.components.push({ component, position });
}
public render(): void {
for (const { component, position } of this.components) {
console.log(component.render(position));
}
}
}
const ui = new UI();
// 添加组件
ui.addComponent("Button", "top-left");
ui.addComponent("Icon", "top-right");
ui.addComponent("Button", "bottom-left"); // 会重用之前创建的 'Button' 对象
ui.addComponent("Icon", "bottom-right"); // 会重用之前创建的 'Icon' 对象
// 渲染用户界面
ui.render();
粒子系统
在模拟自然现象(如烟雾、雨、火花)的粒子系统中,粒子经常有相似的属性和行为,可以通过享元模式高效地管理和重用具有相似属性和行为的粒子。
// npm run code src/code/design-pattern/flyweight/particle-system.ts
export {};
class ParticleFlyweight {
private readonly type: string;
constructor(type: string) {
this.type = type;
}
public animate(x: number, y: number): string {
return `Animating a ${this.type} particle at (${x}, ${y}).`;
}
}
class FlyweightFactory {
private particles: {[key: string]: ParticleFlyweight} = {};
public getParticle(type: string): ParticleFlyweight {
if (!this.particles[type]) {
this.particles[type] = new ParticleFlyweight(type);
}
return this.particles[type];
}
}
class ParticleSystem {
private particles: { particle: ParticleFlyweight; x: number; y: number; }[] = [];
private factory: FlyweightFactory = new FlyweightFactory();
public addParticle(type: string, x: number, y: number): void {
const particle = this.factory.getParticle(type);
this.particles.push({ particle, x, y });
}
public animate(): void {
for (const { particle, x, y } of this.particles) {
console.log(particle.animate(x, y));
}
}
}
const particleSystem = new ParticleSystem();
// 添加粒子
particleSystem.addParticle("Smoke", 1, 1);
particleSystem.addParticle("Rain", 2, 3);
particleSystem.addParticle("Spark", 4, 5);
particleSystem.addParticle("Smoke", 3, 2); // 会重用之前创建的 'Smoke' 粒子
// 动画粒子系统
particleSystem.animate();