Design Pattern | Flyweight Pattern(フライウェイトパターン)

Flyweightパターンとは?

  • Flyweightという英単語は「フライ級」という意味である。ボクシングで最も軽い階級を表す。
  • Flyweightパターンにおける重さは、メモリ使用量である。
  • Flyweightパターンは、インスタンスをできるだけ多く共有してメモリ使用量を減らす方法である。
  • GoFのデザインパターンでは、構造に関するデザインパターンに分類される。

Flyweightパターンのサンプルプログラム

ファイルから大きな文字のテキストを読み取り、それを表示するプログラムである。

Class Diagram
Flyweight Pattern Class Diagram

1. BigCharクラス

大きな文字を表すクラスである。

BigChar.java

package com.devkuma.designpattern.structural.flyweight;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BigChar {

    // 大きな文字を表す文字列('#'、'.'、'\n'の列)
    private String fontData;

    public BigChar(char charName) {
        try {
            ClassLoader loader = BigChar.class.getClassLoader();
            String file = loader.getResource("flyweight/big" + charName + ".txt").getFile();
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String line;
            StringBuffer buf = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                buf.append(line);
                buf.append("\n");
            }
            reader.close();
            this.fontData = buf.toString();
        } catch (IOException e) {
            this.fontData = charName + "?";
        }
    }

    // 大きな文字を表示する。
    public void print() {
        System.out.print(fontData);
    }
}

2. BigCharFactoryクラス

BigCharのインスタンスを共有しながら生成するクラスである。

BigCharFactory.java

package com.devkuma.designpattern.structural.flyweight;

import java.util.HashMap;

public class BigCharFactory {

    // すでに作成したBigCharインスタンスを管理する。
    private HashMap pool = new HashMap();

    private static BigCharFactory singleton = new BigCharFactory();

    private BigCharFactory() {
    }

    // 1つだけのインスタンスを返す。
    public static BigCharFactory getInstance() {
        return singleton;
    }

    // BigCharのインスタンス生成(共有)
    public synchronized BigChar getBigChar(char charName) {
        BigChar bigChar = (BigChar) pool.get("" + charName);
        if (bigChar == null) {
            bigChar = new BigChar(charName);
            pool.put("" + charName, bigChar);
        }
        return bigChar;
    }
}

3. BigStringクラス

BigCharを集めて作った「大きな文字列」を表すクラスである。

BigString.java

package com.devkuma.designpattern.structural.flyweight;

public class BigString {

    private BigChar[] bigChars;

    public BigString(String string) {
        bigChars = new BigChar[string.length()];
        BigCharFactory factory = BigCharFactory.getInstance();
        for (int i = 0; i < bigChars.length; i++) {
            bigChars[i] = factory.getBigChar(string.charAt(i));
        }
    }

    public void print() {
        for (int i = 0; i < bigChars.length; i++) {
            bigChars[i].print();
        }
    }
}

4. Mainクラス

メイン処理を実行するクラスである。

Main.java

package com.devkuma.designpattern.structural.flyweight;

public class Main {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java Main digits");
            System.out.println("Example: java Main 1234");
            System.exit(0);
        }
        BigString bs = new BigString(args[0]);
        bs.print();
    }
}

5. データ

以下のtxtファイルを参照する。
/java-design-pattern-tutorial/src/resources/com/devkuma/designpattern/flyweight

6. 実行結果

以下の結果は、プログラムに引数値として0329を入れて実行した結果である。

....######......
..##......##....
..##......##....
..##......##....
..##......##....
..##......##....
....######......
................
....######......
..##......##....
..........##....
......####......
..........##....
..##......##....
....######......
................
....######......
..##......##....
..........##....
......####......
....##..........
..##............
..##########....
................
....######......
..##......##....
..##......##....
....########....
..........##....
..##......##....
....######......
................

Flyweightパターンのメリット

インスタンスを共有すると、毎回newする必要がなくなるため、メモリ使用量が少ない。より一般的に言えば、インスタンスを共有すると、インスタンスを生成するために必要なリソース量を減らせる。リソースはコンピューターのリソースであり、メモリはリソースの一種である。
時間もリソースの一種である。インスタンスをnewするたびに一定の時間がかかるなら、Flyweightパターンを使ってインスタンスを共有することで、インスタンスをnewする回数を減らせる。そうすることでプログラムの速度を向上させられる。