设计模式(三)

设计模式(三)

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

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

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

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

装饰者模式

装饰者模式(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 小时前
【IO多路转接】高并发服务器实战:Reactor 框架与 Epoll 机制的封装与设计逻辑
linux·运维·服务器·c++·io
HABuo7 小时前
【linux文件系统】磁盘结构&文件系统详谈
linux·运维·服务器·c语言·c++·ubuntu·centos
我在人间贩卖青春8 小时前
C++之多重继承
c++·多重继承
m0_736919108 小时前
C++代码风格检查工具
开发语言·c++·算法
2301_763472469 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
阿猿收手吧!10 小时前
【C++】std::promise原理与实战解析
c++
m0_7066532310 小时前
分布式系统安全通信
开发语言·c++·算法
Zach_yuan11 小时前
深入浅出 JSONCpp
linux·服务器·网络·c++
寻寻觅觅☆11 小时前
东华OJ-基础题-104-A == B ?(C++)
开发语言·c++
lightqjx11 小时前
【C++】unordered系列的封装
开发语言·c++·stl·unordered系列