装饰者模式

Posted m-anonymous

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。

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

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

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

以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之装饰者模式

设计模式整理_装饰者模式

设计模式-装饰者模式(Go语言描述)

设计模式-装饰者模式(Go语言描述)

装饰者模式

设计模式 之 装饰者模式