跳至主要內容

享元模式

约 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();

上次编辑于: