Flyweight パターン

「Flyweight」という英単語は、「フライ級」を意味します。

このパターンは、生成済みのオブジェクトをできるだけ再利用(共有)し、無駄なオブジェクト生成(メモリ使用)を防止する仕組みを提供するパターンです。

このパターンを適用するか否かの判断基準の1つとしては、軽量化対象のクラスが、不変なクラス(イミュータブルなクラス)か否かという事が挙げられます。つまり、軽量化対象が不変でないクラスの場合は、その状態が変更されている場合に再利用できないのでこのパターンに適しません。不変なクラスとはオブジェクトが生成された後にそのオブジェクトの状態が変化しない(フィールド値が不変)ようなクラスのことをいいます。


役割り

1. Flyweight(フライ級)
通常の利用方法だと、多くのオブジェクト(無駄なオブジェクト)を生成され得る可能性のあるクラスです。
2. FlyweightFactory(フライ級の工場)
「Flyweight」を生成管理する工場です。「Flyweight」のオブジェクトが必要な場合は、この工場経由で取得します。生成した「Flyweight」オブジェクトをプールし、共有可能なオブジェクトが要求された場合は、プールからそのオブジェクトを返します。「Flyweight」を管理するファクトリークラスが複数存在すると、再利用できる「Flyweight」を別個に管理(同種の「Flyweight」を複数生成してしまう)してしまうため、「Singleton」パターンを適用します。
3. Client(利用者)
「Flyweight」パターンを適用したクラスを利用し処理します。

▲PageTop

クラス図

Flyweightパターンのクラス図

Flyweightパターン クラス図

▲PageTop

サンプル

ソースコード

1. Flyweight.java

public class Flyweight {
    private int id;
    private int counter;
    public Flyweight(int id) {
        this.id = id;
        System.out.println("Flyweightオブジェクト生成:id=[" + id + "]");
    }
    private int flyweightMethod1(){
        return ++counter;
    }
    public void flyweightMethod2(){
        System.out.println("Flyweight-fM2():id=[" + id + "]/counter=[" +
        flyweightMethod1() + "]");
    }
}

2. FlyweightFactory.java

import java.util.Map;
import java.util.HashMap;

public class FlyweightFactory {
    private static FlyweightFactory singleton = new FlyweightFactory();
    private Map<Integer, Flyweight> pool = new HashMap<Integer, Flyweight>();
    private FlyweightFactory() {}
    public static FlyweightFactory getInstance(){
        return singleton;
    }
    /** マルチスレッドを考慮し、「Synchronized」修飾子を付け、同期化させます。
        同期化させておかないと、無駄なオブジェクトを生成してしまう可能性があるためです。 */
    public synchronized Flyweight getFlyweight(int id){
        Flyweight flyweight = (Flyweight)pool.get(id);
        if (flyweight == null){
            flyweight = new Flyweight(id);
            pool.put(id, flyweight);
        }
        return flyweight;
    }
    }

3. Client.java

public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = FlyweightFactory.getInstance();
        int[] number = new int[]{0,1,2,1,3,4,2,2,3};
        for (int i = 0; i < number.length ; i++ ){
            Flyweight flyweight = factory.getFlyweight(number[i]);
            flyweight.flyweightMethod2();
        }
    }
}

実行結果

C:\sample\desin_pattern\flyweight>javac Client.java [Enter]

C:\sample\desin_pattern\flyweight>java Client [Enter]
Flyweightオブジェクト生成:id=[0]
Flyweight-fM2():id=[0]/counter=[1]
Flyweightオブジェクト生成:id=[1]
Flyweight-fM2():id=[1]/counter=[1]
Flyweightオブジェクト生成:id=[2]
Flyweight-fM2():id=[2]/counter=[1]
Flyweight-fM2():id=[1]/counter=[2]
Flyweightオブジェクト生成:id=[3]
Flyweight-fM2():id=[3]/counter=[1]
Flyweightオブジェクト生成:id=[4]
Flyweight-fM2():id=[4]/counter=[1]
Flyweight-fM2():id=[2]/counter=[2]
Flyweight-fM2():id=[2]/counter=[3]
Flyweight-fM2():id=[3]/counter=[2]
        

▲PageTop