「Flyweight パターン」の版間の差分
編集の要約なし |
|||
26行目: | 26行目: | ||
このソースコードは JDK1.5 以降のバージョンで動作する。 |
このソースコードは JDK1.5 以降のバージョンで動作する。 |
||
< |
<syntaxhighlight lang="java"> |
||
import java.util.Map; |
import java.util.Map; |
||
import java.util.HashMap; |
import java.util.HashMap; |
||
76行目: | 76行目: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
ソースコードとクラス図の対応関係を示す。 |
ソースコードとクラス図の対応関係を示す。 |
2020年7月5日 (日) 22:50時点における版
Flyweight パターン(フライウェイト・パターン)とは、GoFによって定義されたデザインパターンの1つである。 等価なインスタンスを別々の箇所で使用する際に、一つのインスタンスを再利用することによってプログラムを省リソース化することを目的とする。
クラス図
Flyweight パターンのクラス図を以下に挙げる。
概要
Flyweight パターンで設計された API では、利用者は Flyweight
クラスにあたるインスタンスを取得する場合に、直接そのクラスのコンストラクタを呼び出す代わりに FlyweightFactory#getFlyweight()
にアクセスする。
一方、呼び出された FlyweightFactory
オブジェクトは、状況に応じて以下のように振舞う。
- その時点で対象のインスタンスが生成されていない場合
- 対象のインスタンスを新たに生成する。
- 生成したインスタンスをプールする(言い換えると、メンバのコンテナオブジェクトに格納する)。
- 生成されたインスタンスを返す。
- 対象のインスタンスが既に生成されていた場合
- 対象のインスタンスをプールから呼び出す。
- 対象のインスタンスを返す。
このように FlyweightFactory
では状況によって異なる処理が行われるが、利用者側が得る結果は全く同じであるため、利用者は FlyweightFactory
の内部構造を意識せずに使うことが出来るという点が特徴である。
Flyweight パターンを採用すべき典型的な例は、不変なクラスを扱う場合である。不変なクラスとはインスタンスが生成された後にそのインスタンスの状態が変化しないようなクラスであり、Java では
や java.math.BigInteger
などが挙げられる。詳しくはイミュータブルを参照。
java.awt.Color
利用例
Java による Flyweight パターンの例を挙げる。 このソースコードは JDK1.5 以降のバージョンで動作する。
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
class Stamp {
char type;
Stamp(char type){
this.type = type;
}
void print(){
System.out.print(this.type);
}
}
class StampFactory {
Map<Character, Stamp> pool;
StampFactory(){
this.pool = new HashMap<Character, Stamp>();
}
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 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();
}
}
}
ソースコードとクラス図の対応関係を示す。
- Flyweight
- Stamp
- FlyweightFactory
- StampFactory
- FlyweightFactory#getFlyweight()
- StampFactory#get()
このプログラムを実行すると「たかいたけたてかけた」(高い竹立て掛けた)という文字列を出力する。
FlyweightTest#main()
内で StampFactory#get()
を 10 回参照しているが、
そのうち実際に生成されたインスタンスは 5 つ(「た」、「か」、「い」、「け」、「て」)だけであり、
インスタンスが共有されていることが分かる。
注意点
一度 FlyweightFactory
に保存されたインスタンスは、たとえ不要になった場合でもガベージコレクションされることがないため、場合によっては明示的に FlyweightFactory
から削除する必要がある。
関係するパターン
- Singleton パターン
FlyweightFactory
は Singleton として実装されることが多い。