Можно ли реализовать «шаблон стратегии» с помощью аннотаций Java? - PullRequest
2 голосов
/ 20 февраля 2012

Я хочу использовать шаблон стратегии , чтобы реализовать некоторые индивидуальные правила форматирования для членов сторонних классов. Я хочу, чтобы третья сторона должна была сделать не более, чем аннотировать участников класса, чтобы указать, должны ли они использовать стратегию форматирования (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 ]

4 голосов
/ 20 февраля 2012

Я считаю, что это можно сделать с помощью аннотаций, именно так, как вы это предложили.Это будет пример реализации, он также использует шаблон 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 голос
/ 20 февраля 2012

Полагаю, вы обрабатываете этот класс с помощью отражения, поскольку не знаете, какие поля они объявили?

т.е. у вас будет что-то вроде:

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

Какая часть вас волнует? Реализация метода getImplementationOf ()? Это будет стандартный «фабричный» метод для стратегий? Как вы заметили, нет способа напрямую закодировать логику в самой аннотации.

...