装饰模式

概述

装饰模式(Decorator Pattern)是指动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

看下它的结构类图

 

 下面举个例子,代码实现一个这样的场景,我们早上去煎饼摊买煎饼的场景,煎饼可以加蛋和香肠(扩展)

首先实现继承来实现看看

Battercake-煎饼类

public class Battercake {
    protected String getMsg()
    {
        return "煎饼";
    }
    public int getPrice()
    {
        return 5;
    }
}

使用继承BattercakeWithEgg-加鸡蛋

public class BattercakeWithEgg extends Battercake{
    protected String getMsg()
    {
        return super.getMsg() + "加一个鸡蛋";
    }
    public int getPrice()
    {
        return super.getPrice() + 1;
    }
}

加香肠

public class BattercakeWithEggAndSausage extends BattercakeWithEgg{
    protected String getMsg()
    {
        return super.getMsg() + "加一个香肠";
    }
    public int getPrice()
    {
        return super.getPrice() + 2;
    }
}

测试

public class BattercakeTest {
    public static void main(String[] args) {
        Battercake battercake = new Battercake();
        System.out.println(battercake.getMsg() + ",总价格:" + battercake.getPrice());

        Battercake battercakeWithegg = new BattercakeWithEgg();
        System.out.println(battercakeWithegg.getMsg() + ",总价格:" + battercakeWithegg.getPrice());

        Battercake battercakeWithEggAndSausage = new BattercakeWithEggAndSausage();
        System.out.println(battercakeWithEggAndSausage.getMsg() + ",总价格:" + battercakeWithEggAndSausage.getPrice());
    }
}

结果

我们可以看出来继承并不灵活,假如我比较额要加两个蛋,两个香肠怎么办,继续添加子类?显然这样不过灵活

接下来使用装饰模式

抽象类Battercake,可以对应上面类图Component

public abstract class Battercake {
    public abstract String getMsg();
    public abstract int getPrice();
}

具体对象BaseBattercake,不加任何扩展的煎饼

public class BaseBattercake extends Battercake{

    @Override
    public String getMsg() {
        return "煎饼";
    }

    @Override
    public int getPrice() {
        return 5;
    }
}

定义抽象装饰类BattercakeDecorator

public abstract class BattercakeDecorator extends Battercake{
    private Battercake battercake;

    public BattercakeDecorator(Battercake battercake) {
        this.battercake = battercake;
    }

    @Override
    public String getMsg() {
        return this.battercake.getMsg();
    }

    @Override
    public int getPrice() {
        return this.battercake.getPrice();
    }
}

具体装饰类-加鸡蛋的装饰类EggDecorator

public class EggDecorator extends BattercakeDecorator {


    public EggDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    public String getMsg() {
        return super.getMsg() + "+一个鸡蛋";
    }

    @Override
    public int getPrice() {
        return super.getPrice() + 1;
    }
}

具体装饰类-加香肠的装饰类SausageDecorator

public class SausageDecorator extends BattercakeDecorator {


    public SausageDecorator(Battercake battercake) {
        super(battercake);
    }

    @Override
    public String getMsg() {
        return super.getMsg() + "+一个香肠";
    }

    @Override
    public int getPrice() {
        return super.getPrice() + 2;
    }
}

测试类,加2个鸡蛋1根香肠

public class BattercakeDecoratorTest {
    public static void main(String[] args) {
        Battercake battercake = new BaseBattercake();
        battercake = new EggDecorator(battercake);
        battercake = new EggDecorator(battercake);
        battercake = new SausageDecorator(battercake);
        System.out.println(battercake.getMsg() + ",总价:" + battercake.getPrice());
    }
}

结果

 会发现基础类很简单,所有的装饰方法与基础方法分开管理,需要的的时候只需要装饰上就好,就好比一个人可以穿很多种类的衣服,但是我们没必要在Person类中把这些装饰的功能增加进去,而是在需要时动态添加

那么我们什么时候该用装饰模式呢,当我们系统需要新的功能的时候,是向旧的类中添加新的代码,这些新的代码装饰了原有类的核心职责或主要行为,如果在主类中增加新的字段和新的方法无疑增加了类的复杂度,比如期初我们只有一个煎饼类,如果加鸡蛋香肠那么原本的类就会很复杂,新加的东西只是为了满足某个特殊需求,装饰模式提供了很好的解决方案,他把每一个要装饰的功能放在单独的类中,让这个类包装所要装饰的类,所有当有特殊需求时客户端可以有选择、有顺序的选择使用装饰功能

装饰模式的好处就是有效的把类的核心职责和装饰功能分开

posted @ 2019-04-10 20:45  dum  阅读(156)  评论(0编辑  收藏  举报