倭マン's BLOG

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

アノテーションでデザインパターンの役割をマークする (4):クラス・ベース

最後は「クラス・ベースの実現」。 ほどんど「インターフェース・ベースの実現」と同じですが、インターフェースの代わりに(ユーティリティー)クラスを用いているところが違います。 『Effective Java 第2版 (The Java Series)』で「定数インターフェースパターン」の代わりに使うべし、と言われている方法です。

アノテーションの実装


「インターフェース・ベースの実現」と同じような実装ですが、インターフェースの代わりにユーティリティークラス (utility class) を用います。 ユーティリティークラスは次の2つを踏まえた単なるクラスです:

  • private な(デフォルト)コンストラクタのみがある
  • クラス宣言に final を付加されている(なくても別に構いませんが、明示しておく方が親切*1

これらはインスタンスを生成できないようにするためのものです。 この結果、このクラスのメンバーは static でなければいけません。 つまり、アノテーションの定義も (public) static にする必要があります*2

public final class ServiceProvider {

    private ServiceProvider(){}
    
    @Documented
    @Target(ElementType.TYPE)
    public static @interface Service{}

    @Documented
    @Target(ElementType.METHOD)
    public static @interface ProviderRegistration {}

    @Documented
    @Target(ElementType.METHOD)
    public static @interface ServiceAccess {}
    
    @Documented
    @Target(ElementType.TYPE)
    public static @interface Provider {}
}

アノテーションの使用


上記のアノテーションの使用方法は以下のようになります。

// Effective Java 第2版
// 『項目1 コンストラクタの代わりに static ファクトリーメソッドを検討する』より

@ServiceProvider.Service
public interface Service {
    ...  // サービス固有のメソッドをここに
}

@ServiceProvider.Provider
public interface Provider {
    Service newService();
}

public final class Services {
    ...
    @ServiceProvider.ProviderRegistration
    public static void registrerDefaultProvider(Provider p){...}
    
    @ServiceProvider.ProviderRegistration
    public static void registerProvider(String name, Provider p){...}
    
    @ServiceProvider.ServiceAccess
    public static Service newInstance(){...}
    
    @ServiceProvider.ServiceAccess
    public static Service newInstance(String name){...}
}

「インターフェース・ベースの実現」の時と同じく、static インポートを使わずに、どのデザインパターンの役割かを明示する方が個人的には良いかと。

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)


川口耕介氏の新連載『やっぱりJavaがスキ!』がスタート↓
WEB+DB PRESS Vol.50

WEB+DB PRESS Vol.50

*1:『[asin:4873112079:title]』参照。

*2:前回の「インターフェース・ベースの実現」でインターフェースに定義したアノテーションは、自動的に「public static final」となっています。 「クラス・ベースの実現」では、それを明示的にする必要があるというだけです。