Обработка исключений Java через шаблон стратегии? - PullRequest
2 голосов
/ 12 февраля 2010

Я подготовил класс ExceptionHandler<T extends Exception, OptionalReturnType> (см. Ниже), чтобы исключить некоторый (что я вижу как) шаблонный код, который загромождает фактическую реализацию, но в то же время обеспечивает при необходимости ловушку для явной обработки исключений в будущем. По большей части в моем приложении (необходимом для научных расчетов) нет такого понятия, как восстановление из исключений - мне нужен журнал проблемы, чтобы я мог ее исправить, но в противном случае я просто перезапущу один раз проблема исправлена.

Делают ли это другие люди (по крайней мере, в моем конкретном случае применения)? Глупо ли это делать (если да, какое-то объяснение, почему было бы неплохо)?

ExceptionHandler:

public abstract class ExceptionHandler<ExceptionType extends Exception,OptionalReturn> {
 public abstract OptionalReturn handle(ExceptionType e);

//assorted boilerplate ExceptionHandling, e.g.:

 public static <ET extends Exception> ExceptionHandler<ET, ?> swallower(final boolean printStackTrace, final String string) {
  return new ExceptionHandler<ET,Object>() {
   @Override public Object handle(ET e) {
    if(printStackTrace) { e.printStackTrace(); }
    if(string!=null && !string.isEmpty()) { System.err.println(string); }
    return null;
   }
  };
 }

 public static <ET extends Exception> ExceptionHandler<ET, ?> swallower() { return swallower(false,null); }

}

пример использования (который я нахожусь в процессе вырубки, так что я на самом деле не так много пишу):

public class Getter<From> implements Function<Future<? extends From>, From> {

private ExceptionHandler<InterruptedException,?> IEH;
private ExceptionHandler<ExecutionException,?> EEH;

public static final ExceptionHandler<InterruptedException,?> IEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");
public static final ExceptionHandler<ExecutionException,?> EEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");

private Getter() { this(IEH_SWALLOWER,EEH_SWALLOWER); }
private Getter(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    this.IEH = IEH;
    this.EEH = EEH;
}

public static <T> Getter<T> make() { return new Getter<T>(); }

public static <T> Getter<T> make(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    return new Getter<T>(IEH, EEH);
}

@Override public From apply(Future<? extends From> from) {
    if (from==null) throw new NullPointerException("Null argument in call with Getter.");
    return getter(from, IEH, EEH);
}

private static <T> T getter(Future<T> src, ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    try { return src.get(); }
    catch (InterruptedException e) { IEH.handle(e); }
    catch (ExecutionException e) { EEH.handle(e); }
    return null;
    }

}

, который используется с библиотеками Guava для выполнения некоторых смущающе-параллельных вычислений и делает фактическое Iterable преобразование Futures в нечто вроде Iterables.transform(futureCollection,Getter.make()) вместо путаницы внутренних классов и обработки исключений.

Ответы [ 2 ]

2 голосов
/ 12 февраля 2010

Я думаю, что это хорошее решение, но оно может выиграть от ExceptionHandlerFactory и некоторых XML-файлов.

1 голос
/ 12 февраля 2010

Честно говоря, мне трудно понять код. Он полон static, что, как правило, является плохим знаком в ОО-дизайне, и за ним непросто следовать дженерикам.

Разве что-то более простое не понравится и этой работе?

private static <T> T getter(Future<T> src) {
    try { return src.get(); }
     catch (InterruptedException e) { handle( "some text"); }
     catch (ExecutionException e) { handle( e ) }
     return null;
    }

Вы можете реализовать столько базовых методов handle, сколько необходимо в базовом классе (или в статическом служебном классе) и использовать их в блоке catch по мере необходимости. Методы будут выбираться на основе подписи, поэтому, если вы хотите напечатать текст, вы передаете строку, если вы хотите, чтобы трассировка стека передавала исключение (или оба). Что приводит к комбинациям:

handle( String msg )
handle( Exception e )
handle( Exception e, String msg )

В этом решении меньше if, что также является хорошим признаком.

Но я, возможно, упустил момент, учитывая, что код, который вы опубликовали, является лишь выдержкой из всего кода.

Посмотрите иначе на этот вопрос, который также имеет отношение: Сменная стратегия обработки ошибок

EDIT

Если предложенное мной решение слишком просто для ваших нужд, есть два других способа:

public class AbstractGetter<From> implements Function<Future<? extends From>, From> {

private abstract handleInterrupt( Exception e );
private abstract handleExecution( Exception e );

private static <T> T getter(Future<T> src ) {
    try { return src.get(); }
    catch (InterruptedException e) { handleInterrupt(e) }
    catch (ExecutionException e) { handleExecution(e) }
    return null;
    }
}

И вы реализуете конкретный класс X, который соответствует различным стратегиям обработки исключений. По сути это шаблон template .

Вы все еще можете использовать делегирование, но на более грубом уровне. Вместо предоставления отдельного обработчика вы предоставляете стратегию обработчика. Это своего рода разновидность паттерна стратегии .

  public interface ErrorStrategy
  {
        public void handleInterrupt(Exception e);
        public void handleExecution(Exception e);
  }

  public class Getter<From> implements Function<Future<? extends From>, From> {

  ErrorStrategy handler = new DefaultErrorStrategy(). // default one

  public Getter<From>()
  {
  }

  public Getter<From>( ErrorStrategy h )
  {
      this.handler = h.
  }

  private static <T> T getter(Future<T> src ) {
    try { return src.get(); }
    catch (InterruptedException e) { handler.handleInterrupt(e) }
    catch (ExecutionException e) { handler.handleExecution(e) }
    return null;
    }
 }

Вы можете создать нужные вам стратегии обработки ошибок X.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...