设计模式(三)

设计模式(三)

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

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

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

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

装饰者模式

装饰者模式(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

同时继承父类,组合子类

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

相关推荐
渝妳学C25 分钟前
【C++】类和对象(下)
c++
EleganceJiaBao39 分钟前
【C语言】结构体模块化编程
c语言·c++·模块化·static·结构体·struct·耦合
xianwu5431 小时前
反向代理模块。开发
linux·开发语言·网络·c++·git
Bucai_不才1 小时前
【C++】初识C++之C语言加入光荣的进化(上)
c语言·c++·面向对象
木向1 小时前
leetcode22:括号问题
开发语言·c++·leetcode
筑基.1 小时前
basic_ios及其衍生库(附 GCC libstdc++源代码)
开发语言·c++
yuyanjingtao2 小时前
CCF-GESP 等级考试 2023年12月认证C++三级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
越甲八千3 小时前
重温设计模式--代理、中介者、适配器模式的异同
设计模式·适配器模式
王老师青少年编程3 小时前
gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
c++·算法·矩阵·gesp·csp·信奥赛
OTWOL4 小时前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法