Flyweightパターンとは、メモリを節約するために、同じようなオブジェクトを使い回すデザインパターンだ。これにより、同じ状態を共有することで、大量のオブジェクトを効率よく扱うことができる。
たとえば、ゲームの中で木や岩など、同じ形のオブジェクトをたくさん配置する場合、このパターンが役立つ。
では、サンプルコードを一緒に見ていこう。
例えば、何千個もの木を描くとき、全ての木を一つずつ作るのではなく、木の共通部分(形や色など)を使い回して、効率的に木を生成するんだ。
まず、たくさんの木を描くために、木の「種類」を表す `TreeType` というクラスを作る。このクラスは、形や色などの共通部分を持つんだ。木の種類が同じ場合、同じインスタンスを使い回せる。
// 木の種類を表すクラス(フライウェイト)
class TreeType {
constructor(name, color, texture) {
this.name = name;
this.color = color;
this.texture = texture;
}
displayTree(x, y) {
console.log(
`${this.name}の木を位置(${x}, ${y})に描画しました。色: ${this.color}, 質感: ${this.texture}`
);
}
}
次に、たくさんの木を効率的に作るため、木の種類を管理する `TreeFactory` を作ろう。この工場クラスは、すでに同じ種類の木がある場合は、新しく作らずに既存の木の種類を返す。
// 木の種類を管理する工場クラス
class TreeFactory {
constructor() {
this.treeTypes = {}; // すでに作った木の種類を保存する
}
getTreeType(name, color, texture) {
const key = `${name}-${color}-${texture}`;
if (!this.treeTypes[key]) {
this.treeTypes[key] = new TreeType(name, color, texture);
}
return this.treeTypes[key];
}
}
木自体の位置や特定のデータを管理する `Tree` クラスを作るよ。このクラスは、木の種類(`TreeType`)を使い回してメモリを節約する。
// 個別の木を表すクラス
class Tree {
constructor(x, y, treeType) {
this.x = x;
this.y = y;
this.treeType = treeType;
}
display() {
this.treeType.displayTree(this.x, this.y);
}
}
最後に、`TreeFactory` を使って、たくさんの木を効率よく生成して描画する。木の種類が同じ場合、すでに作った木の種類を使い回すから、メモリを節約できるんだ。
// 木の工場を作成
const factory = new TreeFactory();
// 木を生成
const forest = [];
forest.push(new Tree(10, 20, factory.getTreeType("オーク", "緑", "滑らか")));
forest.push(new Tree(30, 40, factory.getTreeType("オーク", "緑", "滑らか")));
forest.push(new Tree(50, 60, factory.getTreeType("松", "濃緑", "針状")));
// 木を描画
forest.forEach(tree => tree.display());
上記のコードでは、同じ種類の木は `TreeFactory` によって一度だけ作られ、それを使い回している。これにより、大量の木を作る場合でも、メモリの無駄遣いを防ぐことができるんだ。
これでFlyweightパターンの解説は終わりだ。
このパターンを使うと、オブジェクトの数が非常に多くなる場面でメモリ消費を抑え、効率的に動作させることができる。