设计模式学习篇-享元模式

43 阅读1分钟

1.概念

共享单元,复用对象(不可变的象)的,节省内存。

2.为什么使用

  • 避免因创建大量对象而导致的内存溢出问题
  • 通过共享对象,提高内存使用效率

4.使用场景

普遍使用一般在对象池,线程池等等这些情况

3.代码实现

  • 通过内部工厂创建共享细粒度对象(相同的部分),减少相同对象的创建,外部管理不同的部分
// 根据怪物表格中的某条数据创建不同的对象

class Unit {
    private _id: number; // 不同
    private _name: string; // 相同
    private _age: number; // 相同

    constructor(name: string, age: number, id: number) {
        this._name = name;
        this._age = age;
        this._id = id;
    }

    public print() {
        console.log(this._name, this._age, this._id);
    }
}
for (let i = 0; i < 10; i++) {
    let u = new Unit('monster', 10, i);
    u.print();
}

class ComUnit {

    private _name: string; // 相同
    public get name(): string {
        return this._name;
    }
    public set name(value: string) {
        this._name = value;
    }
    private _age: number; // 相同
    public get age(): number {
        return this._age;
    }
    public set age(value: number) {
        this._age = value;
    }

    constructor(name: string, age: number) {
        this._name = name;
        this._age = age;
    }
}

let share_count = 0;
// 内部工厂创建对象
class FactoryUnit {
    private _map: Map<string, ComUnit> = new Map<string, ComUnit>();

    public create(name: string, age: number) {
        let key = name + age;
        if (!this._map.has(key)) {
            this._map.set(key, new ComUnit(name, age));
            share_count++;
        }
        console.log('share_count :', share_count);
        return this._map.get(key);
    }
}

let factory = new FactoryUnit();

type newObj = {
    id: number,
    com: ComUnit
}

// 外部管理不同的部分
class UnitMgr {
    private _map: Map<number, newObj> = new Map<number, newObj>();

    public addID(name: string, age: number, id: number) {

        let n = factory.create(name, age);
        this._map.set(id, {
            id: id,
            com: n
        });
    }

    public print(id: number) {
        let u = this._map.get(id);
        console.log(u.com.name, u.com.age, u.id);
    }
}

let mgr = new UnitMgr();
//------
// 用于享元测试
console.log('------------------享元测试分隔符------------------');
for (let i = 0; i < 10; i++) {
    mgr.addID('monster', 10, i);
    mgr.print(i);
}