倭マン's BLOG

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

「GoF デザインパターン」アノテーション (22) : Template Method パターン

今回は Template Method パターン一覧)。

Template Method パターンの登場人物

  • @AbstractClass → 型
    • @TemplateMethod → メソッド
    • @PrimitiveMethod → メソッド
      • method : String
  • @ConcreteClass → 具象クラス
    • abstractClassType : Class<?>

アノテーション定義


上記の定義の具体的な Java コード。

package org.waman.tools.design.gof.behavioral;

import java.lang.annotation.*;

public final class TemplateMethodPattern {
    
    private TemplateMethodPattern(){}

    @Target(ElementType.TYPE)
    public static @interface AbstractClass{

        @Inherited @Target(ElementType.METHOD)
        public static @interface TemplateMethod{}

        @Inherited @Target(ElementType.METHOD)
        public static @interface PrimitiveMethod{
            String method() default "";
        }
    }

    @Target(ElementType.TYPE)
    public static @interface ConcreteClass{
        Class<?> abstractClass() default Void.class;
    }
}

@PrimitiveMethod アノテーションでは、パラメータによってどのテンプレートメソッドから呼ばれているかを指定できるようにしています。 ただし、メソッド名しか指定できないので、メソッドがオーバーロードされていると一意的に識別できません。 まぁ、ある程度の目印って事で。

サンプルコード in 『Java 言語で学ぶデザインパターン入門』


AbstractDisplay.java

@AbstractClass 役のクラス。

import org.waman.tools.design.gof.behavioral.TemplateMethodPattern;
import org.waman.tools.design.gof.behavioral.TemplateMethodPattern.AbstractClass.PrimitiveMethod;
import org.waman.tools.design.gof.behavioral.TemplateMethodPattern.AbstractClass.TemplateMethod;

@TemplateMethodPattern.AbstractClass
public abstract class AbstractDisplay {
    
    @PrimitiveMethod(method="display")
    public abstract void open();
    
    @PrimitiveMethod(method="display")
    public abstract void print();
    
    @PrimitiveMethod(method="display")
    public abstract void close();
    
    @TemplateMethod
    public final void display() {
        open();
        
        for (int i = 0; i < 5; i++)
            print();
        
        close();
    }
}

CharDisplay.java

import org.waman.tools.design.gof.behavioral.TemplateMethodPattern;

@TemplateMethodPattern.ConcreteClass(abstractClass = AbstractDisplay.class)
public class CharDisplay extends AbstractDisplay {
    
    private char ch;
    
    public CharDisplay(char ch) {
        this.ch = ch;
    }

    @Override public void open() {
        System.out.print("<<");
    }

    @Override public void print() {
        System.out.print(ch);
    }

    @Override public void close() {
        System.out.println(">>");
    }
}
import org.waman.tools.design.gof.behavioral.TemplateMethodPattern;

@TemplateMethodPattern.ConcreteClass(abstractClass=AbstractDisplay.class)
public class StringDisplay extends AbstractDisplay {
    
    private String string;
    private int width;
    
    public StringDisplay(String string) {
        this.string = string;
        this.width = string.getBytes().length;
    }
    
    @Override public void open() {
        printLine();
    }
    
    @Override public void print() {
        System.out.println("|" + string + "|");
    }
    
    @Override public void close() {
        printLine();
    }
    
    private void printLine() {...}
}

増補改訂版Java言語で学ぶデザインパターン入門 オブジェクト指向における再利用のためのデザインパターン Code Complete第2版〈上〉―完全なプログラミングを目指して Code Complete第2版〈下〉―完全なプログラミングを目指して