装饰器模式的核心在于继承和委托结合的应用,如果我想要实现一个可以扩展功能的类A,我需要实现他的两个版本,一个是基础实现BasicA,另一个是装饰器ADecorator,他们共同实现了接口A(之前描述为类,此处描述为接口,也确实是有意而为之,体现出了一步抽象)。然后我们的包装器实现全部的接口方法都依靠委托,具体是association式的委托,为了清晰,结构如下——
interface A{
public TYPE NAME(ARGS);//各式各样的接口方法
public TYPE NAME(ARGS);
}
class BasicA implements A{
//fields
private final TYPE data1;
private final TYPE data2;
//Override interface methods
public TYPE NAME(ARGS);
public TYPE NAME(ARGS);
//Other methods
}
class ADecorator implements A{
private final A a; //delegation
public ADecorator(A a){
this.a = a;//association
}
//Override interface methods
public TYPE NAME(ARGS){
return a.NAME(ARGS);//委派实现
}
//etc
}
然后重点在于,多样化的继承ADecorator,这里需要注意的式,装饰器的精髓在于将所要多样化的所有行为彻彻底底的划分为几个不同的方面(互不相干),然后以这几个不同的方面分别多样化的继承装饰器,而我们如何才能将这几个不同的行为组装在一起呢,这里就是装饰器的精彩之处,因为每个ADecorator的实例都有一个委派的属性,这个属性可以指向不同的A具体实现,所以我只需要层层委派,就可以实现功能的层层累加,具体给出一个栈的例子,这个栈的例子还可以看到一点点的单一责任(SRP原则),因为我把一个接口分成了两个——
package learn;
import java.util.*;
interface IStack<E>{
public void push(E item);
public E pop();
public int size();
}
interface UndoAble{
public void undo();
}
interface UndoAbleIStack<E> extends IStack<E>, UndoAble{}
class Stack<E> implements IStack<E>{
private List<E> lst = new ArrayList<>();
public Stack(){}
@Override public void push(E item) { lst.add(item); }
@Override public E pop() { return lst.remove(lst.size() - 1); }
@Override public int size() { return lst.size(); }
}
class StackDecorator<E> implements IStack<E>{
private final IStack<E> s;
public StackDecorator(IStack<E> s) { this.s = s; }
@Override public void push(E item) { s.push(item); }
@Override public E pop() { return s.pop(); }
@Override public int size() { return s.size(); }
}
class UndoStack<E> extends StackDecorator<E> implements UndoAbleIStack<E>{
private List<String> log = new ArrayList<String>();
private List<E> datalog = new ArrayList<>();
public UndoStack(IStack<E> s) { super(s); }
@Override public void push(E item) {
log.add("push");
super.push(item);
}
@Override public E pop() {
log.add("pop");
datalog.add(super.pop());
return datalog.get(datalog.size() - 1);
}
@Override public int size() { return super.size(); }
public void undo() {
String op = log.remove(log.size() - 1);
if(op.equals("push"))
super.pop();
else
super.push(datalog.remove(datalog.size() - 1));
}
}
class LogStack<E> extends StackDecorator<E> implements IStack<E>{
public LogStack(IStack<E> s) { super(s); }
@Override public void push(E item) {
System.out.println("PUSH " + item.toString());
super.push(item);
}
@Override public E pop() {
System.out.println("POP");
return super.pop();
}
@Override public int size() {
System.out.println("GET SIZE");
return super.size();
}
}
public class learn{
public static void main(String[] args) {
UndoAbleIStack<String> logUndoStack = new UndoStack<String>(new LogStack<String>(new Stack<String>()));
logUndoStack.push("zzj1");
logUndoStack.push("zzj2");
logUndoStack.undo();
System.out.println(logUndoStack.pop());
}
}
增添功能只需要给出一个新的子类,并且新创建一个接口就可以了(因为有可能你新给出的子类有原先接口没有给出的方法)。