「Flyweight」という英単語は、「フライ級」を意味します。
このパターンは、生成済みのオブジェクトをできるだけ再利用(共有)し、無駄なオブジェクト生成(メモリ使用)を防止する仕組みを提供するパターンです。
このパターンを適用するか否かの判断基準の1つとしては、軽量化対象のクラスが、不変なクラス(イミュータブルなクラス)か否かという事が挙げられます。つまり、軽量化対象が不変でないクラスの場合は、その状態が変更されている場合に再利用できないのでこのパターンに適しません。不変なクラスとはオブジェクトが生成された後にそのオブジェクトの状態が変化しない(フィールド値が不変)ようなクラスのことをいいます。
Flyweightパターンのクラス図
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]