Flyweight パターン
From Wikipedia, the free encyclopedia
クラス図
Flyweight パターンのクラス図を以下に挙げる。

概要
Flyweight パターンで設計された API では、利用者は Flyweight クラスにあたるインスタンスを取得する場合に、直接そのクラスのコンストラクタを呼び出す代わりに FlyweightFactory.getFlyweight() にアクセスする。
一方、呼び出された FlyweightFactory オブジェクトは、状況に応じて以下のように振舞う。
- その時点で対象のインスタンスが生成されていない場合
- 対象のインスタンスを新たに生成する。
- 生成したインスタンスをプールする(言い換えると、メンバのコンテナオブジェクトに格納する)。
- 生成されたインスタンスを返す。
- 対象のインスタンスが既に生成されていた場合
- 対象のインスタンスをプールから呼び出す。
- 対象のインスタンスを返す。
このように FlyweightFactory では状況によって異なる処理が行われるが、利用者側が得る結果は全く同じであるため、利用者は FlyweightFactory の内部構造を意識せずに使うことができるという点が特徴である。
Flyweight パターンを採用すべき典型的な例は、不変なクラスを扱う場合である。不変なクラスとはインスタンスが生成された後にそのインスタンスの状態が変化しないようなクラスであり、Java では java.math.BigInteger や java.awt.Color などが挙げられる。詳しくはイミュータブルを参照。
利用例
Java による Flyweight パターンの例を挙げる。このソースコードは Java 1.5 以降のバージョンで動作する。
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
class Stamp {
private final char type;
public Stamp(char type) {
this.type = type;
}
public void print() {
System.out.print(this.type);
}
}
class StampFactory {
private final Map<Character, Stamp> pool;
public StampFactory() {
this.pool = new HashMap<Character, Stamp>();
}
public Stamp get(char type) {
Stamp stamp = this.pool.get(type);
if (stamp == null) {
stamp = new Stamp(type);
this.pool.put(type, stamp);
}
return stamp;
}
public int getPoolSize() {
return this.pool.size();
}
}
public class FlyweightTest {
public static void main(String[] args) {
StampFactory factory = new StampFactory();
List<Stamp> stamps = new ArrayList<Stamp>();
stamps.add(factory.get('た'));
stamps.add(factory.get('か'));
stamps.add(factory.get('い'));
stamps.add(factory.get('た'));
stamps.add(factory.get('け'));
stamps.add(factory.get('た'));
stamps.add(factory.get('て'));
stamps.add(factory.get('か'));
stamps.add(factory.get('け'));
stamps.add(factory.get('た'));
for (Stamp s : stamps) {
s.print();
}
System.out.println();
System.out.println("Factory pool size = " + factory.getPoolSize());
}
}
ソースコードとクラス図の対応関係を示す。
- Flyweight
Stamp- FlyweightFactory
StampFactory- FlyweightFactory.getFlyweight()
StampFactory.get()
このプログラムを実行すると「たかいたけたてかけた」(高い竹立て掛けた)という文字列を出力する。FlyweightTest.main() 内で StampFactory.get() を 10 回参照しているが、そのうち実際に生成されたインスタンスは 5 つ(「た」、「か」、「い」、「け」、「て」)だけであり、インスタンスが共有されていることが分かる。
注意点
一度 FlyweightFactory に保存されたインスタンスは、たとえ不要になった場合でもガベージコレクションされることがないため、場合によっては明示的に FlyweightFactory から削除する必要がある。
関係するパターン
- Singleton パターン
FlyweightFactoryは Singleton として実装されることが多い。