倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

FactoryBuilderSupport よ、我に力を! (2) : AbstractFactory クラス

今回は FactoryBuilderSupport に独自のファクトリ・オブジェクトを登録して、オブジェクト生成のロジックを自分で実装できるようにしましょう。 と言いつつ、今回扱うサンプルは前回のものと大差ありませんが。

独自のファクトリ・クラスを作成してビルドできるようにする


手順

  1. 構築する Bean クラスを実装 : MathProblem
  2. Bean クラスを構築するファクトリ・クラスを実装 : MathProblemFactory
  3. ファクトリ・オブジェクトをビルダーに登録
  4. ビルダーでオブジェクトを構築

Bean クラス : MathProblem

まずは構築対象となる Bean クラス。 前回の MathGirl クラスと大して変わりません。

@groovy.transform.ToString
class MathProblem {
    String name
    String solver
    int solvedYear
}

ファクトリ・クラス MathProblemFactory

次は MathProblem オブジェクトを生成するファクトリ・クラス。 ファクトリ・クラスは Factory インターフェース(groovy.util パッケージにあります)を実装するクラスとして作成します。 ただ、通常は同パッケージにある抽象クラス AbstractFactory を継承して作る方が簡単。 このクラスは抽象メソッド newInstance() を実装する必要があります:

class MathProblemFactory extends AbstractFactory{
    
    @Override
    Object newInstance(FactoryBuilderSupport builder, name, value, Map atts) {
        def mp = new MathProblem()

        // 属性からプロパティを注入
        atts.entrySet().each{ entry ->
            mp[entry.key] = entry.value
        }

        return mp
    }
}

前回のサンプルでは自動で行ってくれていたプロパティの注入を、ここでは手動で行っています(後で改善)。

ビルダーへの登録と使用方法

ファクトリ・クラスが実装できたら、これが FactoryBuilderSupport クラスに登録されるようにしておきましょう:

class MathGirlBuilder extends FactoryBuilderSupport{

    MathGirlBuilder(){
        registerBeanFactory('mathGirl', MathGirl)

        // 上で作成したファクトリ MathProblemFactory を登録
        registerFactory('problem', new MathProblemFactory())
    }
}

今回は独自のファクトリ・クラスを使うので、registerFactory() メソッドを使います。

ビルダーでオブジェクトを構築

実装が完了したら、実際にビルダーを使ってみましょう。 ビルダーの使い方自体は前回の MathGirl オブジェクトの生成方法と同じです:

def builder = new MathGirlBuilder()
// MathProblem オブジェクトを生成
def flt = builder.problem(name:'''Fermat's Last Theorem''', solver:'Andrew Wiles', solvedYear:1995)
assert flt.toString() == '''MathProblem(Felmat's Last Theorem, Andrew Wiles, 1995)'''

// もちろん MathGirl オブジェクトも生成できるヨ
def milka = builder.mathGirl(name:'Milka', age:17, ability:'Mathematics')
assert milka.toString() == 'MathGirl(Milka, 17, Mathematics)'

これで完了。

属性の処理を手軽に


最後に、ノードの属性からオブジェクトへのプロパティ注入を簡単に行う方法があるので、それを見ていきましょう。 プロパティの自動注入は、AbstractFactory クラスの onHandleNodeAttributes() メソッドの返り値によって実行を切り替えることができるので、このメソッドをオーバライドして true を返すようにしましょう。 こうすることによって、プロパティ注入が自動で行われるようになります。

class MathProblemFactory extends AbstractFactory{
    
    @Override
    Object newInstance(FactoryBuilderSupport builder, name, value, Map atts) {
        return new MathProblem()
    }

    @Override
    boolean onHandleNodeAttributes(FactoryBuilderSupport builder, node, Map atts) {
        // true を返すことで、オブジェクトへのプロパティ注入が自動で行われる
        return true
    }
}

true を返す前に、属性が保持されている Map パラメータ(上記の atts)を変更することで、注入されるプロパティを操作したりもできそうです。

Groovy for Domain-specific Languages

Groovy for Domain-specific Languages


数学ガール フェルマーの最終定理 (数学ガールシリーズ 2)

数学ガール フェルマーの最終定理 (数学ガールシリーズ 2)