装饰器模式 详解 设计模式

装饰器模式

它允许你在不改变对象结构的情况下,动态地将新功能附加到对象上。

结构:

  • 抽象组件(Component):定义了原始对象和装饰器对象的公共接口或抽象类,可以是具体组件类的父类或接口。
  • 具体组件(Concrete Component):是被装饰的原始对象,它定义了需要添加新功能的对象。
  • 抽象装饰器(Decorator):继承自抽象组件,它包含了一个抽象组件对象,并定义了与抽象组件相同的接口,同时可以通过组合方式持有其他装饰器对象。
  • 具体装饰器(Concrete Decorator):实现了抽象装饰器的接口,负责向抽象组件添加新的功能。具体装饰器通常会在调用原始对象的方法之前或之后执行自己的操作。

图例:

平常假如要加一个配料,都需要修改餐品的源代码,但是随着配料的增多, 类会变得越来越庞大,等下类爆炸了。

java 复制代码
public class Main {
    public static void main(String[] args) {
        FriedNoodles friedNoodles = new FriedNoodles();
        friedNoodles.addBacon();
        friedNoodles.addEgg();
        friedNoodles.addFish();

        System.out.println("Cost: $" + friedNoodles.getCost());
    }
}

案例:

假设有一个简单的咖啡店系统,其中有一个 Coffee 接口表示咖啡,它有一个方法 getCost() 来获取咖啡的价格。现在我们要给咖啡添加一些额外的配料,比如牛奶、摩卡和奶泡。

java 复制代码
// 咖啡接口
interface Coffee {
    double getCost();
}

// 具体咖啡类
class SimpleCoffee implements Coffee {
    @Override
    public double getCost() {
        return 1.0;
    }
}

// 装饰者抽象类
abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee decoratedCoffee) {
        this.decoratedCoffee = decoratedCoffee;
    }

    public double getCost() {
        return decoratedCoffee.getCost();
    }
}

// 具体装饰者类
class Milk extends CoffeeDecorator {
    public Milk(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.5;
    }
}

class Mocha extends CoffeeDecorator {
    public Mocha(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 1.0;
    }
}

class Foam extends CoffeeDecorator {
    public Foam(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.3;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        coffee = new Milk(coffee);
        coffee = new Mocha(coffee);
        coffee = new Foam(coffee);

        System.out.println("Cost: $" + coffee.getCost());
    }
}

通过组合不同的装饰者,可以在不改变原有咖啡对象的情况下,动态地添加额外的功能和费用。

使用场景:

  • 动态地给对象添加功能:当需要给对象动态地添加一些额外的功能,而且这些功能可以独立于该对象的创建。
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

    不能采用继承的情况主要有两类:

    • 第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;
    • 第二类是因为类定义不能继承(如final类)
相关推荐
博风1 分钟前
设计模式:11、迭代器模式(游标)
设计模式·迭代器模式
Lostgreen6 分钟前
分布式查询处理优化之数据分片
大数据·笔记·分布式
hillstream37 分钟前
gitlab工作笔记
笔记·gitlab
夏子曦8 分钟前
java虚拟机——频繁发生Full GC的原因有哪些?如何避免发生Full GC
java·开发语言
gogo_hua9 分钟前
JVM系列之OOM观测准备
java·大数据·jvm
Thomas_YXQ15 分钟前
Unity3D Lua如何支持面向对象详解
开发语言·游戏·junit·性能优化·lua·unity3d
MYBOYER19 分钟前
Kotlin DSL Gradle 指南
android·开发语言·kotlin
m0_6754470820 分钟前
Solon 拉取 maven 包很慢或拉不了,怎么办?
java·maven
武昌库里写JAVA24 分钟前
SpringCloud+SpringCloudAlibaba学习笔记
java·开发语言·算法·spring·log4j
夏天吃哈密瓜26 分钟前
用Scala来解决成绩排名的相关问题
开发语言·后端·scala