ForwardingList
(который extends ForwardingCollection
, который в свою очередь extends ForwardingObject
) реализует шаблон декоратора .
Чтобы использовать, вам просто нужно сделать две вещи:
@Override delegate()
для возврата экземпляра делегата поддержки, который перенаправляет методы на
@Override
любой List
метод, который вы хотите / нужно украсить
Шаблон декоратора позволяет вам использовать композицию вместо наследования ( Effective Java 2nd Edition, Композиция Favor по наследованию ), а ForwardingList
из Guava предоставляет удобный шаблон для написания собственного List
реализация, предоставляя весь сантехнический механизм для вас.
Обратите внимание, что если вы планируете украсить ArrayList
, вы, вероятно, захотите, чтобы ваш подкласс ForwardingList
также реализовал RandomAccess
.
Пример: ListWithDefault
Вот (неполный!) Пример ForwardingList
, который заменяет null
значения в делегате заданным значением по умолчанию.
import java.util.*;
import com.google.common.collect.*;
public class ListWithDefault<E> extends ForwardingList<E> {
final E defaultValue;
final List<E> delegate;
ListWithDefault(List<E> delegate, E defaultValue) {
this.delegate = delegate;
this.defaultValue = defaultValue;
}
@Override protected List delegate() {
return delegate;
}
@Override public E get(int index) {
E v = super.get(index);
return (v == null ? defaultValue : v);
}
@Override public Iterator<E> iterator() {
final Iterator<E> iter = super.iterator();
return new ForwardingIterator<E>() {
@Override protected Iterator<E> delegate() {
return iter;
}
@Override public E next() {
E v = super.next();
return (v == null ? defaultValue : v);
}
};
}
}
Затем мы можем проверить это следующим образом:
public static void main(String[] args) {
List<String> names = new ListWithDefault<String>(
Arrays.asList("Alice", null, "Bob", "Carol", null),
"UNKNOWN"
);
for (String name : names) {
System.out.println(name);
}
// Alice
// UNKNOWN
// Bob
// Carol
// UNKNOWN
System.out.println(names);
// [Alice, null, Bob, Carol, null]
}
Обратите внимание, что это неполная реализация. Метод toString()
по-прежнему возвращает делегат toString()
, который не знает значения по умолчанию. Несколько других методов также должны быть @Override
для более полной реализации.