倭マン's BLOG

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

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

今回は Observer パターン一覧)。

Observer パターンの登場人物

  • @Subject → 型
    • observerType : Class<?>
    • @Observers → フィールド
    • @AddObserver → メソッド
    • @DeleteObserver → メソッド
    • @NotifyObservers → メソッド
    • @GetSubjectStatus → メソッド
  • @ConcreteSubject → 具象クラス
    • subjectType : Class<?>
  • @Observer → 型
    • subjectType : Class<?>
    • @Update → メソッド
  • @ConcreteObserver → 具象クラス
    • observerType : Class<?>

アノテーション定義


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

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

import java.lang.annotation.*;

public final class ObserverPattern {
    
    private ObserverPattern(){}

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

        Class<?> observerType() default Void.class;

        @Inherited @Target(ElementType.FIELD)
        public static @interface Observers{}

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

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

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

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

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

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

        Class<?> subjectType() default Void.class;

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

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

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


NumberGenerator.java

@Subject 役のクラス。

import java.util.*;
import org.waman.tools.design.gof.behavioral.ObserverPattern;
import org.waman.tools.design.gof.behavioral.ObserverPattern.Subject.*;

@ObserverPattern.Subject(observerType = Observer.class)
public abstract class NumberGenerator {
    
    @Observers private List<Observer> observers = new ArrayList<Observer>();
    
    @AddObserver public void addObserver(Observer observer) {
        observers.add(observer);
    }
    
    @DeleteObserver public void deleteObserver(Observer observer) {
        observers.remove(observer);
    }
    
    @NotifyObservers public void notifyObservers() {
        for(Observer obs: observers)
            obs.update(this);
    }
    
    public abstract int getNumber();
    public abstract void execute();
}

RandomNumberGenerator.java

@ConcreteSubject 役の具象クラス。

import java.util.Random;
import org.waman.tools.design.gof.behavioral.ObserverPattern;

@ObserverPattern.ConcreteSubject(subjectType = NumberGenerator.class)
public class RandomNumberGenerator extends NumberGenerator {
    ...
    @Override public int getNumber() {...}
    @Override public void execute() {...}
}

Observer.java

@Observer 役のインターフェース。

import org.waman.tools.design.gof.behavioral.ObserverPattern;
import org.waman.tools.design.gof.behavioral.ObserverPattern.Observer.Update;

@ObserverPattern.Observer(subjectType = NumberGenerator.class)
public interface Observer {
    @Update public abstract void update(NumberGenerator generator);
}

DigitObserver.java, GraphObserver.java

@ConcreteObserver 役の具象クラス。

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

@ObserverPattern.ConcreteObserver(observerType = Observer.class)
public class DigitObserver implements Observer {
    @Override public void update(NumberGenerator generator) {...}
}
import org.waman.tools.design.gof.behavioral.ObserverPattern;

@ObserverPattern.ConcreteObserver(observerType = Observer.class)
public class GraphObserver implements Observer {
    @Override public void update(NumberGenerator generator) {...}
}

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