倭マン's BLOG

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

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

今回は「enum ベースの実現」。 これは役割を指定するための列挙型を別途作成して、アノテーションの引数として使用する方法です。 この enum ベースの方法は、他の3つとチョット感じが違います。

アノテーションの実装


enum ベースの実現」では、

の2つを定義する必要があります:

ServiceProvider.java

@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ServiceProvider {
    
    ServiceProviderRole value();
}

ServiceProviderRole.java

public enum ServiceProviderRole{
    SERVICE,
    PROVIDER,
    PROVIDER_REGISTRATION,
    SERVICE_ACCESS
}

役割を指定する列挙型を @ServiceProvider アノテーションの static なメンバークラスとして定義することもできないことはありません:

@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ServiceProvider {
    
    Role value();

    enum Role{
        SERVICE,
        PROVIDER,
        PROVIDER_REGISTRATION,
        SERVICE_ACCESS
    }
}

このときのアノテーションは @ServiceProvider(ServiceProvider.Role.SERVICE) のようになりますが、ちょっと不格好かな? static インポートを使うと見易くはなりますが。

アノテーションの使用


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

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

import static ServiceProviderRole.*;

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

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

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

アノテーションを付加するターゲット (@Target) を個々の役割で別個に指定することができない(@ServiceProvider(SERVICE) をメソッドに付加することもできる)のが難点かな。

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)


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

WEB+DB PRESS Vol.50