关于享元模式我所知道的

简介: 关于享元模式我所知道的

image.png


关键词:结构型 享元 FlyWeight 性能优化


什么是享元模式?


享元的本质是通过 共享基础类 来处理大量相同的对象。主要是用于性能优化

先看一个简单案例对享元模式有个概念,

需求:现在需要做50串烤肉,50串烤玉米。一般情况下需要准备100根签子串烤串。

但是今天店里只有两根签子,所以我们只能两根签子这样一批批上。

这就是享元模式,拿时间换内存。

// 签子足够的时候
class Skewers {
  constructor(type, skewerIdx) {
    this.type = type;
    this.skewerIdx = skewerIdx;
  }
  showInfo() {
    console.log(`第${this.skewerIdx}根${this.type}签`);
  }
}
for (let i = 0; i < 50; i++) {
  const m = new Skewers("肉", i + 1);
  m.showInfo();
}
for (let i = 0; i < 50; i++) {
  const f = new Skewers("蔬菜", i + 1);
  f.showInfo();
}
// 场景优化后
class Skewers {
  constructor(type) {
    this.type = type;
  }
  showInfo() {
    console.log(`第${this.skewerIdx}根${this.type}签`);
  }
}
const m = new Skewers("肉");
const f = new Skewers("蔬菜");
for (let i = 0; i < 50; i++) {
  f.skewerIdx = i + 1;
  m.skewerIdx = i + 1;
  f.showInfo();
  m.showInfo();
}


应用场景


判断是否需要使用享元模式:

  • 项目中存在大量重复对象
  • 重复的对象为不可变对象,或者一些属性是不可变的。

总而言之需要达到:复用对象,节省内存 的作用。

前端的话,比如:地图上的 cluster 和 mark 都是常用的场景,和绘图相关的都有可能使用到。


如何实现享元模式?


前提:享元对象是不可变对象。

核心:在内存中只保留一份实例,供多处代码引用。

  1. 将需要改写为享元类属性拆分为两个部分,
  • 内在状态:包含不变的、可在许多对象中重用的部分。
  • 外在状态:包含每个对象各自不同的情景数据的成员变量
  1. 保留类中表示内在状态的属性, 并设置为不可修改。这些属性的值只能在 constructor 中获取。
  2. 找到所有使用外在状态成员变量的方法,为方法中所用的每个成员变量新建一个参数, 并使用该参数代替成员变量。
  3. 创建工厂类来管理享元缓存池,它负责在新建享元时检查已有的享元。


// 享元模式
class Flyweight {
  // 内部状态
  private sharedState: any;
  constructor(sharedState: any) {
    this.sharedState = sharedState;
  }
  // 传入外部状态
  public operation(uniqueState): 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);
    }
  }
}
// 找到所有使用外在状态成员变量的方法,为在方法中所用的每个成员变量新建一个参数, 并使用该参数代替成员变量。
function addCarToPoliceDatabase(
  ff: FlyweightFactory,
  plates: string,
  owner: string,
  brand: string,
  model: string,
  color: string
) {
  const flyweight = ff.getFlyweight([brand, model, color]);
  flyweight.operation([plates, owner]);
}
const factory = new FlyweightFactory([
  ["Chevrolet", "Camaro2018", "pink"],
  ["Mercedes Benz", "C300", "black"],
  ["Mercedes Benz", "C500", "red"],
  ["BMW", "M5", "red"],
  ["BMW", "X6", "white"],
]);
factory.listFlyweights();
addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "M5", "red");
addCarToPoliceDatabase(factory, "CL234IR", "James Doe", "BMW", "X1", "red");
factory.listFlyweights();


参考资料


refactoringguru 享元模式

《JavaScript 设计模式与开发实践》

目录
相关文章
|
2月前
|
设计模式 Java
Java设计模式-享元模式(12)
Java设计模式-享元模式(12)
|
3月前
|
设计模式 存储 数据库连接
何时使用享元模式
【8月更文挑战第22天】
25 0
|
5月前
|
设计模式 存储 Java
Java设计模式之享元模式详解
Java设计模式之享元模式详解
|
6月前
|
Java 数据库
享元模式~
享元模式~
|
设计模式 存储 缓存
享元模式【Java设计模式】
享元模式【Java设计模式】
65 0
享元模式【Java设计模式】
|
存储 设计模式 缓存
2023-6-28-第十式享元模式
2023-6-28-第十式享元模式
88 0
|
存储 容器
享元模式(Flyweight)
享元模式(Flyweight)
57 0
|
存储 设计模式 Java
浅谈JAVA设计模式之——享元模式(Flyweight)
运用共享技术有效地支持大量细粒度的对象。
139 0
浅谈JAVA设计模式之——享元模式(Flyweight)
|
存储 缓存 Java
结构型模式-享元模式
结构型模式-享元模式
121 0
|
设计模式 缓存 Java
我学会了,享元模式
享元模式属于结构型模式,这个类型的设计模式总结出了 类、对象组合后的经典结构,将类、对象的结构和使用解耦了,花式的去借用对象。
160 0
我学会了,享元模式