C++装饰器模式:灵活扩展对象功能

问题引出

在面向对象设计与开发里,给已有类添加新职责是常见需求。传统做法是通过继承创建子类来扩展功能,但这容易造成继承层次过深,大大增加系统复杂度。

C++装饰器模式:灵活扩展对象功能

比如,有一个图形类,有圆形、矩形等具体图形类。若要给这些图形添加新功能,像给图形添加边框、填充颜色等,用继承的方式就需要为每个图形类创建多个子类,如带边框的圆形、带颜色填充的圆形等,这样会让继承层次变得很复杂。

而装饰器模式通过组合替代继承的机制,为功能扩展提供了更灵活的方案,避免了继承层次过深的问题。

模式选择

典型结构

在装饰器模式结构中,ConcreteComponent(具体组件)和Decorator(装饰器)均继承自Component基类,共享统一接口。

有人可能会疑惑,为何不直接让Decorator持有ConcreteComponent的指针来实现扩展呢?原因是这种方式仅支持单一组件类型。若新增其他组件类型(如AnotherConcreteComponent),则需重新定义新的装饰器类,违背开闭原则。而通过共享Component基类,装饰器可借助多态特性,适配所有子类对象,实现通用扩展能力,这正是装饰器模式的核心优势。

不过,如果仅需为单一组件类型添加功能,可省略Decorator基类,直接实现具体装饰器。

代码实现

以下是一个完整的C++代码示例:

// Decorator.h
#ifndef _DECORATOR_H_
#define _DECORATOR_H_

// 抽象组件基类
class Component
{
public:
    virtual ~Component() {}
    virtual void Operation() = 0; // 纯虚接口
protected:
    Component() {} // 允许子类构造
};

// 具体组件类
class ConcreteComponent : public Component {
public:
    void Operation() override {
        // 具体组件的操作
        std::cout << "ConcreteComponent operation" << std::endl;
    }
};

// 装饰器基类
class Decorator : public Component {
protected:
    Component* component;
public:
    Decorator(Component* c) : component(c) {}
    void Operation() override {
        if (component) {
            component->Operation();
        }
    }
};

// 具体装饰器类
class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(Component* c) : Decorator(c) {}
    void Operation() override {
        Decorator::Operation();
        // 添加额外功能
        std::cout << "ConcreteDecoratorA added function" << std::endl;
    }
};

class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(Component* c) : Decorator(c) {}
    void Operation() override {
        Decorator::Operation();
        // 添加额外功能
        std::cout << "ConcreteDecoratorB added function" << std::endl;
    }
};
// main.cpp
#include <iostream>
#include "Decorator.h"

int main() {
    // 创建具体组件对象
    Component* concreteComponent = new ConcreteComponent();

    // 用具体装饰器A装饰组件
    Component* decoratedComponentA = new ConcreteDecoratorA(concreteComponent);

    // 用具体装饰器B装饰已经被A装饰过的组件
    Component* decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);

    // 调用操作
    decoratedComponentB->Operation();

    // 释放内存
    delete decoratedComponentB;
    delete decoratedComponentA;
    delete concreteComponent;

    return 0;
}

生活实例理解

生活中咖啡店的饮料定制就是装饰器模式的经典例子。顾客可以点一杯基础咖啡(黑咖啡),之后可以自由选择配料(牛奶、糖、巧克力等)。最终的咖啡价格由基础价格加上所有配料的价格总和组成,而配料的功能(如描述和价格)可以动态叠加,无需为每种组合创建一个独立的类。

在这个例子中,基础咖啡就是ConcreteComponent(具体组件),各种配料就是具体装饰器,它们可以在不改变基础咖啡类的情况下,动态地为咖啡添加新的功能(口味、价格等)。

总结

装饰器模式通过组合替代继承,为对象功能扩展提供了更灵活的方式,避免了继承层次过深带来的复杂性。在C++中,利用多态特性,装饰器可以适配不同的组件对象,实现通用的功能扩展。无论是在编程开发还是生活场景中,装饰器模式都有着广泛的应用。

原创文章,作者:,如若转载,请注明出处:https://zube.cn/archives/152

(0)