Flyweight パターン

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

Flyweight パターン(フライウェイト・パターン)とは、GoFによって定義されたデザインパターンの1つである。 等価なインスタンスを別々の箇所で使用する際に、一つのインスタンスを再利用することによってプログラムを省リソース化することを目的とする。

クラス図[編集]

Flyweight パターンのクラス図を以下に挙げる。

FlyweightFactory クラスは Flyweight インスタンスのコンテナをメンバ変数として持ち、Flyweight オブジェクトを返すメンバ関数 getFlyweight() を実装する。

概要[編集]

Flyweight パターンで設計された API では、利用者は Flyweight クラスにあたるインスタンスを取得する場合に、直接そのクラスのコンストラクタを呼び出す代わりに FlyweightFactory#getFlyweight() にアクセスする。 一方、呼び出された FlyweightFactory オブジェクトは、状況に応じて以下のように振舞う。

その時点で対象のインスタンスが生成されていない場合
  1. 対象のインスタンスを新たに生成する。
  2. 生成したインスタンスをプールする(言い換えると、メンバのコンテナオブジェクトに格納する)。
  3. 生成されたインスタンスを返す。
対象のインスタンスが既に生成されていた場合
  1. 対象のインスタンスをプールから呼び出す。
  2. 対象のインスタンスを返す。

このように FlyweightFactory では状況によって異なる処理が行われるが、利用者側が得る結果は全く同じであるため、利用者は FlyweightFactory の内部構造を意識せずに使うことが出来るという点が特徴である。

Flyweight パターンを採用すべき典型的な例は、不変なクラスを扱う場合である。不変なクラスとはインスタンスが生成された後にそのインスタンスの状態が変化しないようなクラスであり、Java では java.math.BigIntegerjava.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 として実装されることが多い。

関連項目[編集]

外部リンク[編集]