装饰器模式

装饰者模式是一种结构型模式,它对现有的类进行包装,允许向一个现有的对象添加现有的功能,同时又不改变其结构。

这种模式创建了一个新的装饰器类,用来包装原有的类。并在保持类签名完整性的情况下提供了额外的功能。

意图:动态地给一个对象添加额外的职责,就新增红能来说,装饰器模式相比于生成子类更加灵活。

主要解决:通常我们为了增加一个类的功能,经常使用继承的方式,由于继承引入静态代码的特征,并且随着扩展功能的增多,子类会很膨胀。

如何使用;在不想增加子类的情况下使用。

如何解决:将具体功能职责进行划分,同时继承装饰者模式。

关键代码: Component类充当抽象角色,不负责具体实现。 装饰者类继承和引用Component类,具体扩展类重写父类方法。

有点:装饰类和被装饰类可以独立发展,不会互相耦合。装饰模式是继承很好的的一个替代模式。

抽象组件:

public abstract class Beverage {
    String description = "Unknow Beverage";
    public String getDescription(){
        return description;
    }

    public abstract double cost();
}

抽象装饰者类

public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

具体组件

public class Espresso extends Beverage{

    public Espresso(){
        description = "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

具体装饰者

public class Mocha extends CondimentDecorator{
    Beverage beverage;
    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    @Override
    public double cost() {
        return 0.20 + beverage.cost();
    }
}

单元测试

public class MochaTest {

    @Test
    public void getDescription() {
        Beverage beverage = new Espresso();
        beverage = new Mocha(beverage);
        System.out.println(beverage.getDescription());
    }

    @Test
    public void cost() {
        Beverage beverage = new Espresso();
        beverage = new Mocha(beverage);
        System.out.println(beverage.cost());
    }
}

测试结果:
2.19
Espresso, Mocha

装饰者和被装饰者必须是一样的类型,也就是有共同的超类。这是相当关键的地方,所以我们利用继承来达到类型匹配,而不是利用继承获得“行为”。

装饰者在和组件结合时,就是在加入新的行为。所得到的行为并不是继承自超类,而是由组合对象得到的。

如果依赖继承,那么类的行为只能在编译时静态决定。换句话说,行为不是来自超类,就是来自子类覆盖后的版本。但是利用组合,可以把装饰者混合着用,而且是在“运行时".

因此这样就可以在任何时候,实现新的装饰者增加新的行为。如果依赖继承,每当需要新行为时,还得修改现有的代码。

posted @   小兵要进步  阅读(18)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)

侧边栏
点击右上角即可分享
微信分享提示