可以使用Java注释实现“策略模式”吗?

时间:2012-02-20 16:55:12

标签: java design-patterns annotations strategy-pattern

我想使用Strategy Pattern为第三方类中的成员实现一些定制的格式化行为。我希望第三方必须做的只是注释类成员,以指示他们是否应该使用格式策略(A,B或C),然后使用他们的类的实例调用我的'format'函数。然后,我的格式化功能应使用注释来标识需要格式化的成员以及我要使用的格式策略。

public class ThirdPartyClass
{
    @FormatStrategy(fmt=unsigned8,offset=0)
    int memberA;

    @FormatStrategy(fmt=unsigned16,offset=1)
    int memberB;

    @FormatStrategy(fmt=unsigned16,offset=3)
    int memberB;
}

在一个完美的世界中,我希望Java注释支持继承和方法,但似乎并非如此。所以我的问题是,在缺少其中任何一个的情况下,实现这一点的好方法仍然只是用注释触及第三方类?

此致

2 个答案:

答案 0 :(得分:4)

我相信这可以通过注释完成,就像你提出它一样。这将是一个示例实现,它还使用AbstractFactory模式:

class ThirdPartyClass {
    @FormatStrategy(fmt="unsigned8",offset=0)
    int memberA;

    @FormatStrategy(fmt="unsigned16",offset=1)
    int memberB;

    @FormatStrategy(fmt="unsigned16",offset=3)
    int memberC;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FormatStrategy{
    String fmt() default "unsigned8";
    int offset()default 0;
}

interface FormattingStrategy{
    String formatNumber(int number);
}

class BasicFormattingStrategy implements FormattingStrategy{
    private String fmt;
    private int offset;

    private BasicFormattingStrategy(String fmt, int offset) {
        this.fmt = fmt;
        this.offset = offset;
    }

    @Override
    public String formatNumber(int number) {
        // do formatting here
        return "formatted number";
    }

}

interface StrategyFactory{
    FormattingStrategy getStrategy(FormatStrategy fmtStrategy);
}

class DefaultStrategyFactory implements StrategyFactory{

    @Override
    public FormattingStrategy getStrategy(FormatStrategy fmtStrategy) {
        // right now only one strategy implementation exists, but may have many.
        return new BasicFormattingStrategy(fmtStrategy.fmt(), fmtStrategy.offset());
    }

}

以下是实际使用策略的代码:

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException{
    StrategyFactory factory = new DefaultStrategyFactory();
    ThirdPartyClass obj = new ThirdPartyClass();
    Class<ThirdPartyClass> clazz = (Class<ThirdPartyClass>) obj.getClass();
    for(Field field : clazz.getDeclaredFields()){
        FormatStrategy fmtStrategy = field.getAnnotation(FormatStrategy.class);
        if(fmtStrategy != null){
           FormattingStrategy strategy = factory.getStrategy(fmtStrategy);
           String formattedNumber = strategy.formatNumber(field.getInt(obj));
           // use the formatted number
        }
    }
}

显然,您需要进行实际的异常处理/错误检查。

答案 1 :(得分:1)

我假设您正在使用反射处理此类,因为您不知道它们将声明哪些字段?

即。你会有类似的东西:

for (Field f : inputInstance.getClass().getDeclaredFields()) {
  FormatStrategy fs = f.getAnnotation(FormatStrategy.class);
  getImplementationOf(fs).run();
}

您关注哪个部分? getImplementationOf()方法的实现?这将是一种标准的“工厂”式策略方法吗?正如您所观察到的那样,无法将逻辑直接编码到注释本身中。