装饰者模式
装饰者模式的核心就是 装饰者 和 被装饰者 必须是共同的类型,可以是实现共同的接口,或者拥有共同的祖先。
最复杂的应该是这种情况:(多个装饰者和多个被装饰者)(BaseClass 和 Decorator 都是抽象类,)
看到上图,可能有些人就要问了,DecoratorX 和 DecoratorY 能不能直接继承 BaseClass 呢?
在装饰者数量不多的话这样也是可以的,但是比较这两个图,你会发现第一个图结构层次更鲜明,而且更方便管理装饰者。
如果被装饰者只有一个的话,而且装饰者不多的情况下你甚至可以这样:
接下来看个简单的例子吧:(第二个图)
package algorithm.demo; public abstract class Chicken { private String name; public abstract void lay_eggs(); public String getName() { return name; } public void setName(String name) { this.name = name; } }
package algorithm.demo; public class Hen extends Chicken { @Override public void lay_eggs() { // TODO Auto-generated method stub System.out.println("I'm laying eggs"); } }
package algorithm.demo; public class DecoratorX extends Chicken { private Chicken chicken; public DecoratorX(Chicken chicken) { this.chicken = chicken; } @Override public void lay_eggs() { // TODO Auto-generated method stub sing_A_Song(); chicken.lay_eggs(); } public void sing_A_Song() { System.out.println("Before laying eggs,I'd like to sing a song!"); } }
package algorithm.demo; public class DecoratorY extends Chicken { private Chicken chicken; public DecoratorY(Chicken chicken) { this.chicken = chicken; } @Override public void lay_eggs() { // TODO Auto-generated method stub chicken.lay_eggs(); sing_A_Song(); } public void sing_A_Song() { System.out.println("After laying eggs,I'd like to sing a song!"); } }
package algorithm.demo; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Chicken chicken = new Hen(); chicken.lay_eggs(); System.out.println(); chicken = new DecoratorX(chicken); chicken.lay_eggs(); System.out.println(); chicken = new DecoratorY(chicken); chicken.lay_eggs(); } }
结果如下图所示:
通过装饰者模式,我们实现了让母鸡在下蛋前后有了唱歌的行为,扩展了 lay_eggs 的方法。
看到上面的代码你可能看到装饰者的局限性,扩展的行为只能是 BaseClass 里面有的,换句话说,就是只能扩展已有的方法。
那能不能给 BaseClass 添加新的方法呢?答案是可以的,不过你得保证添加新的方法的装饰者必须得在最外层。
package algorithm.demo; public class DecoratorZ extends Chicken { private Chicken chicken; public DecoratorZ(Chicken chicken) { this.chicken = chicken; } @Override public void lay_eggs() { // TODO Auto-generated method stub chicken.lay_eggs(); } public void fly() { System.out.println("咯唧咯唧,I can fly..."); } }
DecoratorZ fly_chicken = new DecoratorZ(chicken); fly_chicken.fly();
那么如果 BaseClass 是一个接口的话呢,若是这样的话,Decorator 就是 BaseClass,就像上图图二一样。
以上纯属个人见解,如有同感,皆大欢喜!若有谬论,还请指正!