设计模式(三)

设计模式(三)

某些情况,可能会过度地使用继承来扩展对象的功能;

由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;

随着子类增多, 各种子类的组合会导致更多子类的膨胀

需要使用对象功能的扩展,能够根据需要来动态地实现,避免扩展功能的增多带来的子类膨胀

装饰者模式

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式通过创建一个包装对象(装饰者)来包裹真实的对象,并提供增强的功能

eg:咖啡

如果我们想要为咖啡添加不同的调料(如糖、牛奶、巧克力等),我们可能需要为每种可能的组合创建一个类

c++ 复制代码
class Coffee {
public:
    virtual std::string getDescription() const = 0;
    virtual double cost() const = 0;
};

class SimpleCoffee : public Coffee {
public:
    std::string getDescription() const override {
        return "Simple Coffee";
    }
    double cost() const override {
        return 10.0;
    }
};

class CoffeeWithMilk : public Coffee {
public:
    std::string getDescription() const override {
        return "Simple Coffee with Milk";
    }
    double cost() const override {
        return 12.0; // Coffee cost + Milk cost
    }
};

class CoffeeWithSugar : public Coffee {
public:
    std::string getDescription() const override {
        return "Simple Coffee with Sugar";
    }
    double cost() const override {
        return 11.0; // Coffee cost + Sugar cost
    }
};

// ... 更多组合类 ...

这种无脑的使用继承,会造成子类过于繁多,臃肿;

解决方法是:

通过组合来增加灵活性,继承是编译时静态决定的;而组合则是运行时,动态地添加或更换组件

​ 继承会导致子类和父类紧密的耦合,父类若变,子类有可能都受影响

​ 组合可以重用 不同类的对象和功能

使用装饰者模式:

创建一个装饰者基类,然后为每种调料创建一个装饰者类

c++ 复制代码
class Coffee {
public:
    virtual std::string getDescription() const = 0;
    virtual double cost() const = 0;
    virtual ~Coffee() {}
};

class SimpleCoffee : public Coffee {
public:
    std::string getDescription() const override {
        return "Simple Coffee";
    }
    double cost() const override {
        return 10.0;
    }
};

// Decorator
class CoffeeDecorator : public Coffee {
protected:
    Coffee* coffee;

public:
    CoffeeDecorator(Coffee* coffee) : coffee(coffee) {}
    std::string getDescription() const override {
        return coffee->getDescription();
    }
    double cost() const override {
        return coffee->cost();
    }
};

// Concrete Decorators
class Milk : public CoffeeDecorator {
public:
    Milk(Coffee* coffee) : CoffeeDecorator(coffee) {}
    std::string getDescription() const override {
        return CoffeeDecorator::getDescription() + ", Milk";
    }
    double cost() const override {
        return CoffeeDecorator::cost() + 2.0; // Milk cost
    }
};

class Sugar : public CoffeeDecorator {
public:
    Sugar(Coffee* coffee) : CoffeeDecorator(coffee) {}
    std::string getDescription() const override {
        return CoffeeDecorator::getDescription() + ", Sugar";
    }
    double cost() const override {
        return CoffeeDecorator::cost() + 1.0; // Sugar cost
    }
};

// ... 更多装饰者类 ...

这样就可以动态的添加调料到咖啡中

c++ 复制代码
int main() {
    Coffee* myCoffee = new SimpleCoffee();
    std::cout << myCoffee->getDescription() << " - $" << myCoffee->cost() << std::endl;

    myCoffee = new Milk(myCoffee);
    std::cout << myCoffee->getDescription() << " - $" << myCoffee->cost() << std::endl;

    myCoffee = new Sugar(myCoffee);
    std::cout << myCoffee->getDescription() << " - $" << myCoffee->cost() << std::endl;

    // Clean up
    delete myCoffee;

    return 0;
}


/*输出:
	Simple Coffee - $10
	Simple Coffee, Milk - $12
	Simple Coffee, Milk, Sugar - $13
*/

可以看到,在装饰者类中

既继承了父类,又定义了父类;即:is-a has-a

同时继承父类,组合子类

通常这种继承父类,又再类中定义了父类,八成是装饰者模式

相关推荐
谭欣辰6 分钟前
LCS(最长公共子序列)详解
开发语言·c++·算法
Cando学算法11 分钟前
鸽笼原理(抽屉原理)
c++·算法·学习方法
郝学胜-神的一滴1 小时前
跨平台动态库与头文件:从原理到命名的深度解析
linux·c++·程序人生·unix·cmake
代码中介商1 小时前
C++ 仿函数(Functor)深度解析:从基础到应用
开发语言·c++
王老师青少年编程1 小时前
csp信奥赛C++高频考点专项训练之字符串 --【字符串基础】:[NOIP 2018 普及组] 标题统计
c++·字符串·csp·高频考点·信奥赛·专项训练·标题统计
冯诺依曼的锦鲤2 小时前
从零实现高并发内存池:TCMalloc 核心架构拆解
c++·学习·算法·架构
Pkmer2 小时前
古法编程: 适配器模式
java·设计模式
无忧.芙桃3 小时前
C++IO库的超详细讲解
开发语言·c++
爱看书的小沐3 小时前
【小沐学GIS】基于C++渲染三维飞行仿真Flight Simulation(OpenGL )第十三期
c++·qt·webgl·opengl·飞行仿真·flight
你撅嘴真丑3 小时前
最大质因子序列
c++