InputStream is = new FileInputStream(file);
DataInputStream dis = new DataInputStream(is);
BufferedInputStream bis = new BufferedInputStream(dis);
Dynamically add a behavior to an object.
Propose a flexible alternative to inheritance.
Occasionally, we want to add a behavior only to certain objects of a class.
Use the decorator pattern when you want to:
add a behavior to an object dynamically and transparently.
add a behavior that can be removed later.
Use the decorator pattern when the creation of subclasses is impractical.
/Component: the object we want to add behavior to
/Decorator: the object that adds behavior to the component.
More flexible than inheritance.
Prevents the creation of complex/heavy classes on the top of a class hierarchy.
Components and decorators are not identical: comparison may not work as expected.
Explosion of small objects.
Interface conformance: components and decorators must implement the same interface.
Omission of the abstract Decorator class.
Lightweight component classes: since decorators specialize the component, the latter should have the less properties as possible.
«Design Patterns: Elements of Reusable Object-Oriented Software.» Erich Gamma, Richard Helm,Ralph Johnson, and John Vlissides. Addison Wesley. October 1994.
InputStream is = new FileInputStream(file);
DataInputStream dis = new DataInputStream(is);
BufferedInputStream bis = new BufferedInputStream(dis);
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
//(...)
Collection<String> tags = new ArrayList();
Collection<String> synchronizedTags = Collections.synchronizedCollection(tags);
Collection<String> readOnlyTags = Collections.unmodifiableCollection(tags);
public static <T> Collection<T> synchronizedCollection(Collection<T> c) {
return new SynchronizedCollection<>(c);
}
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
// (...)
}