装饰者模式

装饰者模式的核心就是 装饰者 和 被装饰者 必须是共同的类型,可以是实现共同的接口,或者拥有共同的祖先。

最复杂的应该是这种情况:(多个装饰者和多个被装饰者)(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,就像上图图二一样。

以上纯属个人见解,如有同感,皆大欢喜!若有谬论,还请指正!

原文地址:https://www.cnblogs.com/M-Anonymous/p/13185323.html