Наследование Java с использованием шаблона компоновщика - PullRequest
10 голосов
/ 18 марта 2011

У меня есть 3 класса:

  1. Ошибка
  2. ShellError
  3. WebError

где

ShellError extends Error 

и

WebError extends Error

В ShellError есть поля, некоторые из которых являются необязательными, а другие обязательными.Я строю объект следующим образом:

shellError = new ShellError.Builder().setFile(filePattern)
.setHost(host).setPath(path).setSource(file.isSource())
.setJobName(p.getJobName()).build();

Поскольку ShellError расширяется Error, я далее:

shellError.setDescription(msg.toString());
shellError.setExceptionClass("MyEvilException");
shellError.setExceptionMessage("Some clever error message");
shellError.setStacktrace(stack);

Итак ... зачем беспокоиться о Builder?Мне нравится тот факт, что моя build () среди прочего удобно проверяет, что все поля установлены правильно и т. Д.

Мне бы понравилось, если бы я мог .. build () ShellError и добавить к нему поля изError класс.

То, что я сделал, работает.

  • Вопрос:

Есть лилучший способ, или имеет смысл то, что я сделал?

- РЕДАКТИРОВАТЬ

Я обновил Builder (), чтобы принимать некоторые параметры, которые были в классе ошибок ранее.Теперь у меня есть

shellError = new ShellError.Builder(exception, "Some description").setFile(filePattern).setHost(host)
.setPath(path).setSource(file.isSource()).
setJobName(p.getJobName()).build();

Что ты скажешь? лучше?Хуже?

Ответы [ 3 ]

14 голосов
/ 23 декабря 2011

Шаблон , популяризированный Джошем Блохом, имеет несколько преимуществ , но он не так элегантно работает на родительских / подклассах, как объяснено в в этом обсуждении наши коллеги в мире C # . Лучшее решение, которое я видел до сих пор, это это (или небольшой вариант этого).

5 голосов
/ 18 марта 2011

Исходя из функций, на которые вы ссылались, это явно не стандартный класс java.lang.Error .Обычно сборщики используются для того, чтобы можно было легко создавать неизменяемый объект или предоставлять функциональность, аналогичную «именованным параметрам», в случаях, когда имеется множество параметров конфигурации / построения.

Для этого конкретного случая это будетболее разумно, если бы класс Error был неизменным после построения, и если эти дополнительные установочные функции были в конструкторе, а не в классе ошибок.Я не знаю, насколько у вас есть контроль над любым из этих классов, но если вы можете изменить их, я бы посоветовал сначала сделать так, чтобы сборщик поддерживал те же установщики, чтобы вы могли выполнить всю настройку в сборщике.Затем, если это возможно, вы можете попробовать удалить эти методы установки и вместо этого разрешить их настройку из конструктора.Если у вас нет никакого контроля над ними, вы можете потенциально расширить класс построителя другим классом, который поддерживает эти дополнительные методы.

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

0 голосов
/ 14 июня 2013

Как уже говорилось, шаблон компоновщика не может органично вписаться в существующую политику инициализации объектов Java.Существует несколько подходов для достижения требуемого результата.Хотя, конечно, всегда лучше избегать неоднозначных практик, это не всегда возможно.Мой хак основан на API отражения Java с обобщениями:

abstract public class AbstractClass {

    public static class Builder {

        public <T extends AbstractClass> T build(Class<T> implementingClass) {
            try {
                Constructor<T> constructor = implementingClass
                        .getConstructor(new Class[]{Builder.class});
                return constructor.newInstance(this);
            } catch (NoSuchMethodException e) {
                // TODO handle the exception
            } catch (InvocationTargetException | InstantiationException |
                     IllegalAccessException  e) {
                // TODO handle the exception
            }
        }
    }

    protected AbstractClass(Builder builder) {

    }
}

public class ImplementingClass extends AbstractClass {

    public ImplementingClass (Builder builder) {
        super(builder);
    }
}

Инициализация:

ImplementingClass instance = new AbstractClass.Builder()
                    .build(ImplementingClass.class);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...