装饰者模式的核心是定义一个可以互相嵌套的装饰这类来解决嵌套问题。
这个模式 我还没有完全理解,我就直接照搬head first书上的例子:我们在星巴克点饮料的时候 我们可能添加各种各样的调味料。
如果我们不加修改 我们可能得到上面的一个基类,但是存在很多问题,1对于一个杯茶 可能不能加牛奶,但是他是包含添加milk的选项。2对于一杯咖啡 我们可能会加2份牛奶,那么我们需要彻底修改上面的代码
在装饰者中,我们把主题看做装饰体,在上面的例子中饮料就是装饰体,我们把可以添加到装饰体的物品看做装饰品,在上述例子中调味料就是装饰品,我们要求我们的装饰品能装饰装饰体或者包含着装饰体的装饰品,换句话说就是对于一个装饰体能有0个或者多个装饰品,这就要求装饰体和装饰品类型兼容,这个通过共同继承一个超类或者实现一个接口来实现。
这里给出一个例子来说明
这里饮料杯定义成装饰体 而调味料被定义成装饰品,调味料中包含着对一个饮料对象的引用,这个饮料对象可以指向一种具体饮料,或者包含着其他调味料的饮料,这样我们可以根据需要进行自定义无限嵌套。
===========================================
2015年1月24日17:33:57
今天又重新看了装饰者模式 有得到一点新的理解
装饰者模式还是符合那个装饰体和装饰品的关系模式,我们使用装饰者模式的目的是为了对原来类做一个包装以扩展他的功能,举个例子说明
//这里定义一个数组的接口,用来存储一个int数组 并提供根据index获取Num的方法 public interface NumListInterface{ public int getNum(int index); public int getSize(); } public class NumList implements NumListInterface{ private int[] numArray; public NumList(int[] nl){ numArray=nl; } //这里按照正常的方式来实现数组 public int getNum(int index){ ...... } public int getSize(){ ... } }
上面定义完了,现在来了一个新需求:我们需要对数组进行循环访问,也就是可以传进去index>= size的情况,这里我们该怎么做呢
我们可以定义一个装饰品
//定义装饰体的超类 (这个可以不要,但是装饰品的基本结构就是这样) public abstract class modify implements NumListInterface{ NumListInterface NL; public modify(NumListInterface NL){ this.NL=NL; } <pre name="code" class="java"> public int getNum(int index){ NL.getNum(index); } public int getSize(){ NL.getSize(); }
}
//装饰品
public class round extends modify{ <pre name="code" class="java"> public int getNum(int index){ NL.getNum(index%NL.getSize()); } public int getSize(){ NL.getSize(); }
}
这样我们只需要把之前声明的NumList对象装入一只装饰品中,我们通过公共接口访问就能得到我们的目的,
同样的我们可以实现用getNum 访问第N个奇数index节点或者偶数index节点,另外我们可以将这几个装饰品嵌套起来,达到组合效果,比如循环访问第N个奇数等
这样的设计能保证我们的程序对扩展开放,而对修改封闭,也就是开闭原则,
另外我们需要注意一点,装饰者模式中装饰品访问自己指向而对装饰品的深度只有一层,这样也在一定程度上保证了我们整个装饰链的可修改性,比如上面的点饮料,我们可能开始点了一份咖啡 加两勺糖,这里我们要取消一勺,我们只需要抽掉一层装饰品就可以了。
在java中这样的设计很常见,具体可以参考java io的设计
注意:装饰者模式要求程序依赖于统一的超类或者接口,如果程序依赖于某一具体类,那么装饰者模式将失效,这不难理解。