倭マン's BLOG

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

「GoF デザインパターン」アノテーション (1) : AbstractFactory パターン

今回から、GoF 本に載っているデザインパターンについて、役割をマークするアノテーションを定義していってみましょう(一覧)。

今回は AbstractFactory パターン

AbstractFactory パターンの登場人物

  • @Factory → パッケージ
  • @AbstractFactory → 型
    • @CreateProduct → メソッド
      • productType : Class<?>
  • @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) {...}
}

増補改訂版Java言語で学ぶデザインパターン入門 オブジェクト指向における再利用のためのデザインパターン