浅入了解装饰器模式

装饰器模式的核心在于继承和委托结合的应用,如果我想要实现一个可以扩展功能的类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());
	}
	
}

增添功能只需要给出一个新的子类,并且新创建一个接口就可以了(因为有可能你新给出的子类有原先接口没有给出的方法)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值