设计模式- 装饰器模式(Decorator Pattern)结构|原理|优缺点|场景|示例

本文详细介绍了装饰器模式,包括其分类、工作原理、角色和优缺点,以及在Java和Python中的代码示例,展示了如何在运行时动态为对象添加新功能,保持接口一致性并支持功能组合。
摘要由CSDN通过智能技术生成

                                     设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式     责任链模式     命令模式    备忘录模式          状态模式         访问者模式        中介者模式 


装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地给对象添加新的职责(功能)或改变其原有行为。装饰器模式通过创建一个装饰器类,该类包装(持有)原始对象,并在保持原始对象接口不变的前提下,通过代理或继承的方式添加新的功能。装饰器模式可以提供比继承更灵活的扩展方式,因为它可以在不修改原有类的情况下,为对象添加新功能,并且可以叠加多个装饰器以实现多重增强。

模式结构

装饰器模式通常包含以下角色:

  1. 组件接口(Component):定义了基础功能的接口,所有具体组件和装饰器都要实现这个接口,以便于保持接口的一致性。

  2. 具体组件(Concrete Component):实现了组件接口,是需要被装饰的基础对象。

  3. 装饰器(Decorator):实现了组件接口,并持有一个组件接口类型的引用,用于存储被装饰的对象。装饰器可以在实现组件接口方法的基础上,添加新的职责或修改原有行为。

  4. 具体装饰器(Concrete Decorators):继承自装饰器类,为具体组件添加新的职责或修改其行为。具体装饰器可以在构造函数中接收被装饰的对象,并在实现组件接口方法时调用被装饰对象的对应方法。

工作原理

  • 客户端:创建具体组件对象,并根据需要通过装饰器对其进行装饰。客户端始终面向组件接口编程,无需关心对象是否被装饰以及如何装饰。
  • 装饰器:持有一个组件接口类型的引用,用于存储被装饰的对象。装饰器在实现组件接口方法时,可以调用被装饰对象的对应方法,并在此基础上添加新功能或修改原有行为。
  • 具体装饰器:在构造函数中接收被装饰的对象,并在实现组件接口方法时调用被装饰对象的对应方法,同时添加新的职责或修改原有行为。

优缺点

优点
  • 开放封闭原则:装饰器模式遵循“开闭原则”,允许在不修改原有类的情况下,动态地为对象添加新功能,增强了系统的可扩展性。
  • 灵活性:可以使用多个装饰器对同一个对象进行多次装饰,从而实现不同组合的增强功能。
  • 透明性:装饰后的对象与未装饰的对象在对外接口上保持一致,客户端无需关心对象是否被装饰以及如何装饰,只需面向组件接口编程。
缺点
  • 过度使用可能导致类层次过深:如果过度使用装饰器模式,可能会导致类的层次过深,增加系统的复杂性。
  • 不易于理解:对于不熟悉装饰器模式的开发人员来说,可能需要花费更多时间理解装饰器的实现逻辑。

适用场景

  • 需要为对象动态添加新功能,且新功能与原有功能可独立变化:装饰器模式可以在运行时为对象添加新功能,新功能与原有功能通过装饰器类进行封装,二者可以独立变化。
  • 需要保持类的开放封闭原则,避免修改已有代码:装饰器模式可以在不修改原有类的情况下,通过创建装饰器类为对象添加新功能,符合开放封闭原则。
  • 需要为对象提供多种可选的附加功能,且这些功能可以自由组合:通过使用多个装饰器对同一对象进行装饰,可以实现不同组合的增强功能。

代码示例(以Java为例)

// 组件接口
interface Coffee {
    double getCost();
    String getDescription();
}

// 具体组件
class SimpleCoffee implements Coffee {
    @Override
    public double getCost() {
        return 10.0;
    }

    @Override
    public String getDescription() {
        return "Simple coffee";
    }
}

// 装饰器
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

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

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

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}

// 具体装饰器
class MilkCoffee extends CoffeeDecorator {
    public MilkCoffee(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

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

    @Override
    public String getDescription() {
        return super.getDescription() + ", with milk";
    }
}

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

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

    @Override
    public String getDescription() {
        return super.getDescription() + ", with vanilla";
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Coffee simpleCoffee = new SimpleCoffee();
        System.out.println(simpleCoffee.getDescription() + " costs " + simpleCoffee.getCost());  
        // 输出:Simple coffee costs 10.0

        Coffee milkCoffee = new MilkCoffee(simpleCoffee);
        System.out.println(milkCoffee.getDescription() + " costs " + milkCoffee.getCost());  
        // 输出:Simple coffee, with milk costs 12.0

        Coffee vanillaMilkCoffee = new VanillaCoffee(milkCoffee);
        System.out.println(vanillaMilkCoffee.getDescription() + " costs " + vanillaMilkCoffee.getCost());  
        // 输出:Simple coffee, with milk, with vanilla costs 15.0
    }
}

 在这个Java示例中:

  • Coffee接口作为组件接口,定义了获取咖啡价格和描述的方法。
  • SimpleCoffee类是需要被装饰的具体组件,实现了基础的咖啡功能。
  • CoffeeDecorator类作为装饰器,实现了Coffee接口,并持有一个Coffee类型的引用,用于存储被装饰的对象。装饰器类实现了getCost()getDescription()方法,但并未添加新功能,主要是为了方便具体装饰器类的继承。
  • MilkCoffeeVanillaCoffee类是具体装饰器,分别继承自CoffeeDecorator,并在构造函数中接收被装饰的对象。它们在实现getCost()getDescription()方法时,调用了被装饰对象的对应方法,并在此基础上添加了新功能(牛奶和香草)的费用和描述。
  • 客户端代码创建SimpleCoffee对象,并根据需要通过装饰器对其进行装饰,最终得到添加了牛奶和香草的咖啡。客户端始终面向Coffee接口编程,无需关心对象是否被装饰以及如何装饰。

代码示例(以Python为例)

# 组件接口
class Coffee:
    def get_cost(self):
        raise NotImplementedError("Subclasses must implement this method")

    def get_description(self):
        raise NotImplementedError("Subclasses must implement this method")

# 具体组件
class SimpleCoffee(Coffee):
    def __init__(self):
        self.cost = 10
        self.description = "Simple coffee"

    def get_cost(self):
        return self.cost

    def get_description(self):
        return self.description

# 装饰器
class CoffeeDecorator(Coffee):
    def __init__(self, decorated_coffee: Coffee):
        self.decorated_coffee = decorated_coffee

    def get_cost(self):
        return self.decorated_coffee.get_cost()

    def get_description(self):
        return self.decorated_coffee.get_description()

# 具体装饰器
class MilkCoffee(CoffeeDecorator):
    def __init__(self, decorated_coffee: Coffee):
        super().__init__(decorated_coffee)
        self.cost = decorated_coffee.get_cost() + 2
        self.description = decorated_coffee.get_description() + ", with milk"

class VanillaCoffee(CoffeeDecorator):
    def __init__(self, decorated_coffee: Coffee):
        super().__init__(decorated_coffee)
        self.cost = decorated_coffee.get_cost() + 3
        self.description = decorated_coffee.get_description() + ", with vanilla"

# 客户端代码
def main():
    simple_coffee = SimpleCoffee()
    print(simple_coffee.get_description(), "costs", simple_coffee.get_cost())  # 输出:Simple coffee costs 10

    milk_coffee = MilkCoffee(simple_coffee)
    print(milk_coffee.get_description(), "costs", milk_coffee.get_cost())  # 输出:Simple coffee, with milk costs 12

    vanilla_milk_coffee = VanillaCoffee(milk_coffee)
    print(vanilla_milk_coffee.get_description(), "costs", vanilla_milk_coffee.get_cost())  # 输出:Simple coffee, with milk, with vanilla costs 15

if __name__ == "__main__":
    main()

在这个Python示例中:

  • Coffee类作为组件接口,定义了获取咖啡价格和描述的接口。
  • SimpleCoffee类是需要被装饰的具体组件,实现了基础的咖啡功能。
  • CoffeeDecorator类作为装饰器,实现了组件接口,并持有一个Coffee类型的引用,用于存储被装饰的对象。装饰器类实现了get_cost()get_description()方法,但并未添加新功能,主要是为了方便具体装饰器类的继承。
  • MilkCoffeeVanillaCoffee类是具体装饰器,分别继承自CoffeeDecorator,并在构造函数中接收被装饰的对象。它们在实现get_cost()get_description()方法时,调用了被装饰对象的对应方法,并在此基础上添加了新功能(牛奶和香草)的费用和描述。
  • 客户端代码创建SimpleCoffee对象,并根据需要通过装饰器对其进行装饰,最终得到添加了牛奶和香草的咖啡。客户端始终面向Coffee接口编程,无需关心对象是否被装饰以及如何装饰。
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式(State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值