今回は AbstractFactory クラス(Factory インターフェース)に定義されている isXxxx() メソッドを見ていきます。
AbstractFactory クラスに定義されている isXxxx() メソッドは次の2つ:
- isLeaf() メソッド
- isHandlesNodeChildren() メソッド
もちろん、どちらも返り値は boolean です。 AbstractFactory のデフォルト実装(と Bean ファクトリ*1)での各メソッドの返り値は下表のようになってます:
isXxxx() メソッド | AbstractFactory クラス | Bean ファクトリ |
---|---|---|
isLeaf() | false | false |
isHandlesNodeChildren() | false | false |
では、それぞれのメソッドをもう少し詳しく見ていきましょう。
isLeaf() メソッド
isLeaf() メソッドは構築しようとしているノードが末端要素、つまり子ノードを持たないかどうかを返します。 持たない場合は true、持つ場合は false が返されます。
もし isLeaf() メソッドが true を返す場合、子ノードを構築しようとすると RuntimeException が投げられます。 また、このとき子ノードが構築されないので、同ファクトリ・オブジェクトの
- isHandleNodesChildren() メソッド
- onNodeChildren() メソッド
- setChild() メソッド
は呼ばれません。
では、isLeaf() が true を返すようにしたサンプルコードを見てみましょう:
/* Bean クラス */ class Leaf{} /* Leaf クラスのファクトリ */ class LeafFactory extends AbstractFactory{ @Override Object newInstance(FactoryBuilderSupport builder, name, value, Map map) { return new Leaf() } // isLeaf() が true を返すように設定 @Override boolean isLeaf() { return true } } /* ビルダー */ class TreeBuilder extends FactoryBuilderSupport{ TreeBuilder(){ registerFactory('leaf', new LeafFactory()) } } // スクリプト def builder = new TreeBuilder() try{ builder.leaf{ // RuntimeException が投げられる leaf() } assert false }catch(RuntimeException e){ assert true }
leaf ノードが子要素を持っているので、ビルダーによる構築時に RuntimeException が投げられます。
isHandlesNodeChildren() メソッド
isHandlesNodeChildren() メソッドは構築しようとしているノードの「子ノードを操作する」かどうかを返します。 ここで「子ノードを操作する」とは、同ファクトリ・オブジェクトの onNodeChildren() メソッドを呼び出すかどうかということです。 注意が必要なのは、isHandlesNodeChildren() メソッドの返り値に関係なく、子ノードの(対応するファクトリによる)構築は行われます。
isHandlesNodeChildren() メソッドが false を返す場合のサンプルを見てみましょう:
/* Bean クラスその1 */ class Leaf{} /* Leaf のファクトリ */ class LeafFactory extends AbstractFactory{ // Leaf オブジェクトが生成されたら "Create Leaf" と表示 @Override Object newInstance(FactoryBuilderSupport builder, name, value, Map map) { println 'Create Leaf' return new Leaf() } } /* Bean クラスその2 */ class Branch{} /* Branch のファクトリ */ class BranchFactory extends AbstractFactory{ @Override Object newInstance(FactoryBuilderSupport builder, name, value, Map map) { return new Branch() } // isHandesNodeChildren() が false を返すように設定 @Override boolean isHandlesNodeChildren() { return false } // 呼ばれるとアサーションが失敗 @Override boolean onNodeChildren(FactoryBuilderSupport builder, node, Closure content) { assert false } } /* ビルダー */ class TreeBuilder extends FactoryBuilderSupport{ TreeBuilder(){ registerFactory('leaf', new LeafFactory()) registerFactory('branch', new BranchFactory()) } } // スクリプト def builder = new TreeBuilder() def tree = builder.branch{ leaf() // "Create Leaf" と表示される }
このスクリプトは例外が投げられずに終了し、標準出力に "Create Leaf" と表示されます。 BranchFactory の onNodeChildren() メソッドは呼ばれず、一方、LeafFactory の newInstance() メソッドは呼ばれています。
Groovy for Domain-specific Languages
- 作者: Fergal Dearle
- 出版社/メーカー: Packt Publishing
- 発売日: 2010/05/30
- メディア: ペーパーバック
- この商品を含むブログ (9件) を見る
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2011/03/02
- メディア: ペーパーバック
- 購入: 19人 クリック: 779回
- この商品を含むブログ (91件) を見る
*1:FactoryBuilderSupport クラスに registerBeanFactory() メソッドで登録される Factory オブジェクト