设计模式(三)

设计模式(三)

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

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

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

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

装饰者模式

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

同时继承父类,组合子类

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

相关推荐
是小胡嘛4 小时前
C++之Any类的模拟实现
linux·开发语言·c++
口袋物联4 小时前
设计模式之工厂模式在 C 语言中的应用(含 Linux 内核实例)
linux·c语言·设计模式·简单工厂模式
Want5956 小时前
C/C++跳动的爱心①
c语言·开发语言·c++
lingggggaaaa7 小时前
免杀对抗——C2远控篇&C&C++&DLL注入&过内存核晶&镂空新增&白加黑链&签名程序劫持
c语言·c++·学习·安全·网络安全·免杀对抗
phdsky7 小时前
【设计模式】建造者模式
c++·设计模式·建造者模式
H_-H7 小时前
关于const应用与const中的c++陷阱
c++
小毛驴8507 小时前
软件设计模式-装饰器模式
python·设计模式·装饰器模式
coderxiaohan7 小时前
【C++】多态
开发语言·c++
gfdhy7 小时前
【c++】哈希算法深度解析:实现、核心作用与工业级应用
c语言·开发语言·c++·算法·密码学·哈希算法·哈希
ceclar1238 小时前
C++范围操作(2)
开发语言·c++