今回から、GoF 本に載っているデザインパターンについて、役割をマークするアノテーションを定義していってみましょう(一覧)。
今回は AbstractFactory パターン。
AbstractFactory パターンの登場人物
- @Factory → パッケージ
- @AbstractFactory → 型
- @CreateProduct → メソッド
- productType : Class<?>
- @CreateProduct → メソッド
- @AbstractProduct → 型
- factoryType : Class<?>
- @ConcreteFactory → 具象クラス
- factoryType : Class<?>
- @ConcreteProduct → 具象クラス
- productType : Class<?>
- @Client → 型
- factoryType : Class<?>
最初 @Client 役を忘れていたので、付け足しました。
アノテーション定義
上記の定義の具体的な Java コード。
package org.waman.tools.design.gof.creational; import java.lang.annotation.*; public final class AbstractFactoryPattern { private AbstractFactoryPattern(){} @Target(ElementType.PACKAGE) public static @interface Factory{} @Target(ElementType.TYPE) public static @interface AbstractFactory{ @Inherited @Target(ElementType.METHOD) public static @interface CreateProduct{ Class<?> productType() default Void.class; } } @Target(ElementType.TYPE) public static @interface AbstractProduct{ Class<?> factoryType() default Void.class; } @Target(ElementType.TYPE) public static @interface ConcreteFactory{ Class<?> factoryType() default Void.class; } @Target(ElementType.TYPE) public static @interface ConcreteProduct{ Class<?> productType() default Void.class; } @Target(ElementType.TYPE) public static @interface Client{ Class<?> factoryType() default Void.class; } }
サンプルコード in 『Java 言語で学ぶデザインパターン入門』
Factory.java
@AbstractFactory 役のクラス。
package sample.gof.creational.abstract_factory.factory; import org.waman.tools.design.gof.creational.AbstractFactoryPattern; import org.waman.tools.design.gof.creational.AbstractFactoryPattern.AbstractFactory.CreateProduct; @AbstractFactoryPattern.AbstractFactory public abstract class Factory { ... @CreateProduct(productType = Link.class) public abstract Link createLink(String caption, String url); @CreateProduct(productType = Tray.class) public abstract Tray createTray(String caption); @CreateProduct(productType = Page.class) public abstract Page createPage(String title, String author); }
Item.java, Link.java, Tray.java, Page.java
@AbstractProduct 役のクラス群。 面倒なのでまとめて定義していますが、通常、public クラスは1つのファイルには定義できません。
package sample.gof.creational.abstract_factory.factory; import org.waman.tools.design.gof.creational.AbstractFactoryPattern; public abstract class Item { ... public abstract String makeHTML(); } @AbstractFactoryPattern.AbstractProduct(factoryType = Factory.class) public abstract class Link extends Item {...} @AbstractFactoryPattern.AbstractProduct(factoryType = Factory.class) public abstract class Tray extends Item {...} @AbstractFactoryPattern.AbstractProduct(factoryType = Factory.class) public abstract class Page {...}
Item クラスは Product ではないので、アノテーションは付加していません。
ListFactory.java
@ConcreteFactory 役のクラス。
package sample.gof.creational.abstract_factory.listfactory; import org.waman.tools.design.gof.creational.AbstractFactoryPattern; import sample.gof.creational.abstract_factory.*; @AbstractFactoryPattern.ConcreteFactory(factoryType = Factory.class) public class ListFactory extends Factory { @Override public Link createLink(String caption, String url) {...} @Override public Tray createTray(String caption) {...} @Override public Page createPage(String title, String author) {...} }
ListLink.java, ListTray.java, ListPage.java
@ConcreteProduct 役のクラス群。
package sample.gof.creational.abstract_factory.listfactory; import org.waman.tools.design.gof.creational.AbstractFactoryPattern; import sample.gof.creational.abstract_factory.factory.*; @AbstractFactoryPattern.ConcreteProduct(productType = Link.class) public class ListLink extends Link { ... @Override public String makeHTML() {...} } @AbstractFactoryPattern.ConcreteProduct(productType = Tray.class) public class ListTray extends Tray { ... @Override public String makeHTML() {...} } @AbstractFactoryPattern.ConcreteProduct(productType = Page.class) public class ListPage extends Page { ... @Override public String makeHTML() {...} }
Main.java
@Client 役のクラス。
import org.waman.tools.design.gof.creational.AbstractFactoryPattern; @AbstractFactoryPattern.Client(factoryType = Factory.class) public class Main { public static void main(String[] args) {...} }