【Gang of Four】デザインパターン学習 - Fly Weight


Fly Weight - 軽い物

目次
書中では何やら難しいことが色々と書いてありますが、要するに同じオブジェクトを複数回作成していると色々な面で高コストになるので、Factoryクラスを作成しインスタンスを生成するのは一度きりとすることでそれを回避しましょうね。というのが本パターンの主旨です。

目的

多数の細かいオブジェクトを効率よくサポートするために共有を利用する。

構成要素

・Flyweight 同一インスタンスを大量に生成する必要があるオブジェクトの抽象クラス
・ConcreteFlyweight Flyweightの具象クラス
・UnsharedConcreteFlyweight Flyweightクラスを管理するクラス 行、列など子としてFlyweightクラスを保持するクラス
・FlyweightFactory Flyweightクラスを生成するクラス
・Client 使用者

実装

※UnsharedConcreteFlyweightに相当するクラスはありません。
文字オブジェクト管理するサンプルコードを書きます。書中のサンプルコードも文字オブジェクトが例になっているので同じようなものになってしまいますが。

ConcreteFlyweight Flyweightの具象クラス

文字クラス
文字を1文字管理するクラス

Character.kt
package flyweight

class Character(private val character: Char) {
    fun print() {
        print(character)
    }
}

FlyweightFactory Flyweightクラスを生成するクラス

文字製造クラス
文字クラスのインスタンスを生成、プールするファクトリークラスを作成します。
当該クラスにて一度生成したオブジェクトをプールすることにより、以前生成したことのあるオブジェクトを再度生成しない。

CharacterFactory.kt
package flyweight

// シングルトンオブジェクトにする
object CharacterFactory {

    val characterPool = HashMap<AllCharacter, Character>()

    enum class AllCharacter(val value: Char) {
        A('A'),
        B('B'),
        C('C'),
        D('D'),
        E('E'),
        F('F'),
        G('G'),
        H('H'),
        I('I'),
        J('J'),
        K('K'),
        L('L'),
        M('M'),
        N('N'),
        O('O'),
        P('P'),
        Q('Q'),
        R('R'),
        S('S'),
        T('T'),
        U('U'),
        V('V'),
        W('W'),
        X('X'),
        Y('Y'),
        Z('Z')
    }

    fun getCharacterObject(characterType: AllCharacter): Character {
        // 未生成であれば、当該インスタンスをプールする。
        characterPool[characterType]?.let {
            return it
        } ?: run {
            val char = Character(characterType.value)
            characterPool[characterType] = char
            return char
        }
    }
}

Client 使用者

文字を使う人
BANANAを生成します。

Client.kt
package flyweight

class Client {
    init {
        val characters = ArrayList<Character>()
        // "BANANA"を生成します
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.B))
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.A))
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.N))
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.A))
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.N))
        characters.add(CharacterFactory.getCharacterObject(CharacterFactory.AllCharacter.A))

        characters.forEach {
            it.print()
        }
    }
}

出力結果

[output]
BANANA