JDC has provided a good way to keep track.
I would like to make important points.
The decorator template allows you to create a class that adorns another class by adding or removing dynamically new responsibility for the instance.
In your case, you want to add responsibility.
Decorator is not an annoying drawing, but the decorator's class must match the class that it decorates.
Thus, in your case, having a decorator that comes from the Collection interface does not correspond to the decorated object, since List has methods that Collection does not have.
Your need is to decorate List instances, so the decorator should be inferred from the List type.
In addition, the decorator class can, in accordance with its needs, process before and after the class that it decorates, but is also responsible for invoking the original operation of the decorated class.
In your case, you want to know if an item has been added or removed from the list. To achieve this, since the result of the method has consequences for whether you write information or not, it is preferable to delegate the processing to the decorated object first, and then your decorator can perform its processing.
Sometimes you do not need to decorate a method, do not do this, but do not forget to delegate the decorated object accordingly.
import java.util.Iterator; import java.util.List; public class DecoratorList<T> implements List<T> { private static final Tracer tracer = ....; private List<T> decorated; private DecoratorList(List<T> decorated) { this.decorated=decorated; } // no decorated methods .... @Override public int size() { return this.decorated.size(); } @Override public boolean isEmpty() { return this.decorated.isEmpty(); } @Override public boolean contains(Object o) { return this.decorated.contains(o); } @Override public Iterator<T> iterator() { return this.decorated.iterator(); } .... // end no decorated methods // exemple of decorated methods @Override public void add(int index, T element) { tracer.info("element " + element + " added to index " + index); this.decorated.add(index,element); } @Override public boolean remove(Object o) { final boolean isRemoved = this.decorated.remove(o); if (isRemoved){ tracer.info("element " + o + " removed"); } return isRemoved; } }
As explained, the decorator is not intrusive for decorated items.
Thus, the idea does not change your code, which works, but adds a decoration operation immediately after the list is instantiated.
If you do not program by interface when declaring list variables, then you declare ArrayList list = new ArrayList() instead of List list = new ArrayList() , of course, you must change the declared type to List, but it does not violate the code, vice versa.
Here is your sample code:
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(123); LinkedList<Integer> anotherNewList = new LinkedList<Integer>(); anotherNewList.add(333);
Now you can do this:
List<Integer> list = new ArrayList<Integer>(); list = new DecoratorList<Integer>(list);
To make the task easier and safer, you can even create a utility method for applying the decoration to the list:
private static <T> List<T> decorateList(List<T> list) { list = new DecoratorList<T>(list); return list; }
and name it like this:
List<Integer> list = new ArrayList<Integer>(); list = decorateList(list);