设计模式演化之装饰模式

定义

向现有的对象添加新的功能,并不改变其结构

演化

1.饮品是生活中最常见的物质,它是一个种类庞大的家族。先定义一个抽象的饮品类,它只有一个属性weight来表示重量。

public abstract class Drink {

    private int weight;

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

2.之后就可以通过继承自Drink来定义一些实际的饮品类。如Water,Sugar,Honey

public class Water extends Drink {

}
public class Sugar extends Drink {

}

3.使用继承的办法,逐步建立起了饮品家族。当有n个饮品种类时,需要继承自Drink创建n个实际饮品类。此时这个继承关系只有一层,比较清晰。现在复杂化场景,请给出一杯糖水:我们会发现这个简单的SugarWater几乎没有办法定义了,Java是不支持多继承的,它没有办法同时继承自Water,Sugar类从而获得这二者的属性。那只能另辟蹊径,让SugarWater先继承自Water,再给它补充Sugar的属性才行。

public class SugarWater extends Water {

    private Sugar sugar;

    public SugarWater(Sugar sugar) {
        this.sugar = sugar;
    }
    
    @Override
    public int getWeight() {
        return super.getWeight() + sugar.getWeight();
    }
}

这时就产生了第二层的继承结构。这第二层可以组合方式将会有Cn2种。当三种饮品组合在一起的时候,将会出现第三层继承结构,组合方式有Cn3种…按照这种写法下去,Drink的产品族数量直接爆炸了。当形成继承链之后,较底层的类的变化也势必会影响较上层的类。

4.由3可知使用继承的办法对于多层次复杂的场景是难以适应的,此时就需要用到装饰模式了。直接定义一个装饰类DrinkWrapper。它继承自Drink,但同时又能持有一个Drink类型的参数。也就是说,它拥有了和一个Drink对象互相组合的能力,从而避开了对继承的使用。并且由于隔开了和实际对象的直接访问,还可以再额外附加一些修饰性的功能。

public class DrinkWrapper extends Drink {
    
    private Drink drink;

    public DrinkWrapper(Drink drink) {
        this.drink = drink;
    }
    
    @Override
    public int getWeight() {
        return super.getWeight() + drink.getWeight();
    }
}

在这种情况下,创建一个糖水对象的过程就交给了调用方去处理

    public static void display() {
        Drink waterWrapper = new DrinkWrapper(new Water());
        Drink sugarWater = new DrinkWrapper(waterWrapper);
    }

装饰模式的使用就解决了继承结构冗余的问题,它只需要定义一些实际类,它们都只继承自一个统一抽象类或实现一个接口。后续对于这些组合都通过逐步包装的方式实现,而不再需要继承的方法。对于n个产品,只需要n个实现类及一个包装类即可。

优点:

(1)避免使用继承方式扩展带来的灵活性差,无限扩展问题
(2)可以动态的扩展一个对象的功能,还可以选择不同的装饰器,从而实现不同的行为
(3)组件类与装饰类可以独立变化,用户可以自由组合组件类与装饰类来获取不同的功能

缺点:

(1)如果基类被改变,则更容易影响全局
(2)结构过深,容易出错,且不容易排查
(3)装饰层数不能过多,否则影响效率

使用场景:

(1)不影响其他对象情况下,动态透明地给它添加功能
(2)需要动态给对象增加功能,这些功能还支持撤销
(3)不能使用继承方式扩展,或者继承不利于系统扩展维护

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值