Должен ли я расширить ArrayList для добавления атрибутов, которые не являются нулевыми? - PullRequest
8 голосов
/ 20 февраля 2012

Я хотел бы добавить коллекцию объектов в arrayList, только если конкретный атрибут не равен нулю.

Я думаю о расширении ArrayList и реализации проверки внутри дочернего класса.

Один альтернативный способ - проверить атрибут перед тем, как поместить его в Arraylist, но это будет означать, что мне придется разбрасывать проверки if везде, если мне нужно добавить объекты в arraylist, основываясь на логике.

Хотелось бы узнать ваши мысли об этом ... если подумать, это перебор?

Ответы [ 4 ]

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

Шаблон декоратора

Я бы действительно рекомендовал обернуть ArrayList, используя хорошо документированный Декоратор . Вы просто заключаете в ArrayList другую реализацию List, которая делегирует большинство методов, но добавляет логику проверки:

public class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{

    private final List<MyBusinessObject> target;

    public ValidatingListDecorator(List<MyBusinessObject> target) {
        this.target = target;
    }

    @Override
    public MyBusinessObject set(int index, MyBusinessObject element)
    {
        validate(element);
        return target.set(index, element);
    }

    @Override
    public boolean add(MyBusinessObject o)
    {
        validate(o);
        return target.add(o);
    }

    //few more to implement

}

Преимущества:

  • При желании вы все равно можете получить доступ к необработанному списку без проверки (но вы можете ограничить это)
  • Проще складывать разные проверки, выборочно включать и выключать их.
  • Способствует составлению по наследству , как отмечено @ helios
  • Улучшает тестируемость
  • Не привязывает вас к конкретной реализации List, вы можете добавить проверку в LinkedList или Hibernate постоянные списки. Вы даже можете подумать о универсальном Collection декораторе для проверки любой коллекции.

Замечания по реализации

Несмотря на реализацию, помните, что при переопределении нужно помнить множество методов: add(), addAll(), set(), subList() (?) И т. Д.

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

Хороший ОО дизайн

Наконец я написал:

validate(element)

но учтите:

element.validate()

что лучше дизайн.

Проверка стека

Как отмечалось ранее, если вы хотите объединить валидацию, валидацию каждого свойства / объекта в одном отдельном классе, рассмотрите следующую идиому:

public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{

    private final List<MyBusinessObject> target;

    public ValidatingListDecorator(List<MyBusinessObject> target) {
        this.target = target;
    }

    @Override
    public MyBusinessObject set(int index, MyBusinessObject element)
    {
        validate(element);
        return target.set(index, element);
    }

    protected abstract void validate(MyBusinessObject element);

}

... и несколько реализаций:

class FooValidatingDecorator extends ValidatingListDecorator {

    public FooValidatingDecorator(List<MyBusinessObject> target)
    {
        super(target);
    }

    @Override
    protected void validate(MyBusinessObject element)
    {
        //throw if "foo" not met
    }
}

class BarValidatingDecorator extends ValidatingListDecorator {

    public BarValidatingDecorator(List<MyBusinessObject> target)
    {
        super(target);
    }

    @Override
    protected void validate(MyBusinessObject element)
    {
        //throw if "bar" not met
    }
}

Хотите проверить только foo ?

List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);

Хотите проверить foo и bar ?

List<MyBusinessObject> list = 
  new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
1 голос
/ 20 февраля 2012

Я не думаю, что это хорошая практика. Вместо этого попробуйте написать Util-Method в Util-Class, принимая два параметра: список массивов и объект, который вы хотите добавить. Там вы можете проверить все, что захотите, и повторно использовать логику по всему коду.

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

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

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

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

Проблема возникает только в том случае, если вы собираетесь повторно использовать этот код и не помните, что переопределили класс ArrayList, обязательно тщательно прокомментируйте.

...