定义:运用共享技术有效地支持大量细粒度的对象

类比:就像在一个大型会议上,每个参会者都有一个名字牌,但他们的椅子和桌子是共享的。这样可以减少资源消耗

应用场景

  • 需要生成大量相似对象
  • 对象的大部分状态可以外部化并且共享

优缺点

  • 优点
    • 减少了内存消耗
    • 提高性能
  • 缺点
    • 增加系统的复杂性
    • 需要确保共享对象的状态是外部化且可共享的

实现代码

// 享元类
class Flyweight {
  private sharedState: any;
 
  constructor(sharedState: any) {
    this.sharedState = sharedState;
  }
 
  public operation(uniqueState: any): void {
    const s = JSON.stringify(this.sharedState);
    const u = JSON.stringify(uniqueState);
    console.log(`Flyweight: Displaying shared (${s}) and unique (${u}) state.`);
  }
}
 
// 享元工厂
class FlyweightFactory {
  private flyweights: { [key: string]: Flyweight } = <any>{};
 
  constructor(initialFlyweights: string[][]) {
    for (const state of initialFlyweights) {
      this.flyweights[this.getKey(state)] = new Flyweight(state);
    }
  }
 
  private getKey(state: string[]): string {
    return state.join('_');
  }
 
  public getFlyweight(sharedState: string[]): Flyweight {
    const key = this.getKey(sharedState);
 
    if (!(key in this.flyweights)) {
      console.log('FlyweightFactory: Can\'t find a flyweight, creating new one.');
      this.flyweights[key] = new Flyweight(sharedState);
    } else {
      console.log('FlyweightFactory: Reusing existing flyweight.');
    }
 
    return this.flyweights[key];
  }
 
  public listFlyweights(): void {
    const count = Object.keys(this.flyweights).length;
    console.log(`\nFlyweightFactory: I have ${count} flyweights:`);
    for (const key in this.flyweights) {
      console.log(key);
    }
  }
}
 
// 客户端代码
const factory = new FlyweightFactory([
  ['Chevrolet', 'Camaro2018', 'pink'],
  ['Mercedes Benz', 'C300', 'black'],
  ['Mercedes Benz', 'C500', 'red'],
  ['BMW', 'M5', 'red'],
  ['BMW', 'X6', 'white'],
]);
 
factory.listFlyweights();
 
// 添加一个汽车到警察数据库
function addCarToPoliceDatabase(
  ff: FlyweightFactory, plates: string, owner: string, brand: string, model: string, color: string,
) {
  console.log('\nClient: Adding a car to database.');
  const flyweight = ff.getFlyweight([brand, model, color]);
  
  // 客户端将享元和独特的状态传递给享元对象的操作方法
  flyweight.operation([plates, owner]);
}
 
addCarToPoliceDatabase(factory, 'CL234IR', 'James Doe', 'BMW', 'M5', 'red');
addCarToPoliceDatabase(factory, 'CL234IR', 'James Doe', 'BMW', 'X1', 'red');
 
factory.listFlyweights();