定义
享元模式,是一种结构型涉及模式,它通过共享尽可能多的相似对象来减少内存,特别使用于大量对象几乎相同的情况。
它通过将对象的状态分为内部状态和外部状态来实现共享。
UML 类图
typescript 实现
1. 创建享元类
class Flyweight {
private intrinsicState: string;
constructor(intrinsicState: string) {
this.intrinsicState = intrinsicState;
}
public operation(extrinsicState: string): void {
console.log(`Flyweight: Intrinsic State - ${this.intrinsicState}, Extrinsic State - ${extrinsicState}`);
}
}
2. 创建享元工厂
class FlyweightFactory {
private flyweights: {[key: string]: Flyweight} = {};
constructor(initialFlyweights: string[]) {
for(const state of initialFlyweights) {
this.flyweights[state] = new Flyweight(state);
}
}
public getFlyweight(intrinsicState: string): Flyweight {
if (!(intrinsicState in this.flyweights)) {
console.log('FlyweightFactory: Cannot find a flyweight, creating new one.');
this.flyweights[intrinsicState] = new Flyweight(intrinsicState);
} else {
console.log('FlyweightFactory: Reusing existing flyweight.');
}
return this.flyweights[intrinsicState];
}
public listFlyweights(): void {
const count = Object.keys(this.flyweights).length;
console.log(`FlyweightFactory: I have ${count} flyweights`);
for(const key in this.flyweights) {
console.log(key);
}
}
}
3. 使用示例
const factory = new FlyweightFactory(['state1', 'state2', 'state3']);
factory.listFlyweights();
通用实现
1. 工厂函数方式
// 公共代码
export const FlyweightFactory = (function() {
const instances = new Map<string, any>();
function getMapKey(Constructor: Function, args: any[]): string {
return Constructor.name + JSON.stringify(args);
}
return {
getFlyweight<T>(Constructor: new(...args: any[]) => T, args: any[]): T {
const key = getMapKey(Constructor, args);
if(instances.has(key)) {
return instances.get(key);
} else {
const instance = new Constructor(...args);
instances.set(key, instance);
return instance;
}
},
removeFlyweight<T>(Constructor: new(...args: any[]) => T, args: any[]): void {
const key = getMapKey(Constructor, args);
if(instances.has(key)) {
instances.delete(key);
}
},
listFlyweights(): void {
for(let [key, value] of instances.entries()) {
console.log(`Key: ${key}, Instance: ${value}`);
}
}
}
})();
// 私有代码,使用示例
class Hi {
prvaite name: string;
constructor(name: string) {
this.name = name;
}
}
const hi1 = FlyweightFactory.getFlyweight(Hi, ["wenix"]);
const hi2 = FlyweightFactory.getFlyweight(Hi, ["wenix2"]);
console.log(hi1 === hi2);
2. 类方式
// 公共代码
export class Flyweight<T> {
private readonly Constructor: { new(...args: any[]): T };
private instances = new Map<string, T>();
constructor(Constructor: new (...args: any[]) => T) {
this.Constructor = Constructor;
}
public getFlyweight(args: any[]): T {
const key = JSON.stringify(args);
let instance = this.instances.get(key);
if(!instance) {
instance = new this.Constructor(...args);
this.instances.set(key, instance);
}
return instance;
}
public removeFlyweight(args: any[]): void {
const key = JSON.stringify(args);
if(this.instances.has(key)) {
this.instances.delete(key);
}
}
public listFlyweight() {
for(let [key, value] of this.instances.entries()) {
console.log(`Key: ${key}, Instance: ${value});
}
}
}
// 私有代码,使用示例
class Hi {
private name: string;
constructor(name: string) {
this.name = name;
}
}
const HiFlyweight = new Flyweight(Hi);
const hi1 = HiFlyweight.getFlyweight(["wenix"]);
const hi2 = HiFlyweight.getFlyweight(["wenix2"]);
console.log(hi1 === hi2);