装饰者模式

定义:

动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性
的替代方案。

相信大家应该都吃过火锅了,火锅中锅底是必须的,至于其他的配菜就需要自己点了。

下面以火锅来谈谈装饰者模式。

首先需要创建一个火锅的对象,后面鸳鸯火锅,麻辣火锅,清汤火锅等都继承它

abstract class Pot {

    //锅底名
    public String name = "锅底";

    public String getName() {
        return name;
    }

    //价格,由子类实现
    public abstract double price();
}

因为每个锅底的价格都不一样,所以写一个抽象的price()方法,由子类决定价格。

然后定义定义火锅的实例: 清汤锅底、鸳鸯锅底等。

清汤锅底:

class ClearSoupPot extends Pot {

    public ClearSoupPot(){
        name = "清汤锅底";
    }

    @Override
    public double price() {
        return 29;
    }
}

鸳鸯锅底

class YuanYangPot extends Pot {

    public YuanYangPot(){
        name = "鸳鸯锅底";
    }

    @Override
    public double price() {
        return 39;
    }
}

锅底已经键好了,现在我们需要加配菜了。首先创建一个配菜的抽象类,所有配菜都继承自它。

abstract class Garnish extends Pot{
    public abstract String getName();
}

因为我们的配菜是来搭配火锅的,所以要继承Pot类。

//蔬菜类
class GarnishVegetables extends Garnish {

    private Pot mPot;

    public GarnishVegetables(Pot pot){
        mPot = pot;
    }

    @Override
    public String getName() {
        return mPot.getName() + "  +蔬菜";
    }

    @Override
    public double price() {
        return mPot.price() + 12;
    }
}

为了让配菜类能够引用到火锅对象,所以在初始化的时候传入火锅对象。

同理创建GarnishDuckBlood、GarnishShrimp鸭血和虾的类。

现在我们可以点一份喜欢的火锅了。

    public static void main(String[] args){

        //点一份鸳鸯锅底
        Pot pot = new YuanYangPot();
        //加鸭血
        pot = new GarnishDuckBlood(pot);
        //加蔬菜
        pot = new GarnishVegetables(pot);

        //打印菜单
        System.out.println(pot.getName());
        //打印价格
        System.out.println(pot.price());

        //点一份清汤锅底
        Pot soupPot = new ClearSoupPot();
        //加虾
        soupPot = new GarnishShrimp(soupPot);
        //加蔬菜
        soupPot = new GarnishVegetables(soupPot);

        //打印菜单
        System.out.println(soupPot.getName());
        //打印价格
        System.out.println(soupPot.price());
    }

执行结果如下:

鸳鸯锅底  +鸭血  +蔬菜
57.0

清汤锅底   + 虾  +蔬菜
77.0

这里我们可以把火锅当初一个被装饰的对象,它初始时只有对应的锅底。而各种配菜则是装饰品,添加到火锅中,使其具有不同的配菜。

通过装饰者模式,可以动态的给对象添加一些额外的职责。

装饰者模式的通用结构

  • Component 抽象组件

Component 是一个接口或抽象对象,是我们定义的最基本、最核心的组件。是被修饰的对象父类,如上面的火锅类pot。

  • ConcreteComponent 具体组件

ConcreteComponent 是组件Component 的实现类,是我们要装饰的具体对象,如上面的鸳鸯锅,清汤锅。

  • Decorator 装饰角色

一般是一个抽象类,继承自Component。

  • 具体的装饰角色 ConcreteDecoratorA,ConcreteDecoratorB

继承自Decorator 类,是装饰者Decorator 的实例。如上面的蔬菜,鸭血,虾都是装饰者

抽象组件代码清单

Component :组件定义

abstract class Component {
    //抽象方法,可有可无
    abstract void operate();

}

ConcreteComponent 组件的实例对象定义

class ConcreteComponent extends  Component {
    @Override
    void operate() {
        System.out.println("做一些事");
    }
}

Decorator 抽象装饰者

abstract class Decorator extends Component{

    private Component mComponent = null;

    //通过构造函数传递被修饰者
    public Decorator(Component component){
        this.mComponent = component;
    }

    //委托给被修饰者执行
    @Override
    void operate() {
        this.mComponent.operate();
    }
}

ConcreteDecoratorA、ConcreteDecoratorB具体的装饰类定义

class ConcreteDecoratorA extends Decorator {

    //定义被修饰者
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    //定义自己的修饰方法
    private void m1(){
        System.out.println("方法1 修饰");
    }

    //重写父类方法
    @Override
    void operate() {
        this.m1();
        super.operate();
    }
}

class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }


    public void m2(){
        System.out.println("方法2 修饰");
    }

    //重写父类方法
    @Override
    void operate() {
        this.m2();
        super.operate();
    }
}

执行装饰者模式:

    public static void main(String[] args){

        Component component = new ConcreteComponent();
        //第一次修饰
        component = new ConcreteDecoratorA(component);
        //第二次修饰
        component = new ConcreteDecoratorB(component);
        //修饰后运行
        component.operate();
    }

执行结果:

方法2 修饰
方法1 修饰
做一些事

优缺点

装饰者模式可以动态的增加类的功能,但如果使用过量会增加会出现很多小对象,让程序变得复杂。

参考:《Head First设计模式》

上一篇:OpenJ_Bailian - 3151 : Pots


下一篇:在未来给我们看病的将是医疗机器人?