设计模式(三)

设计模式(三)

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

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

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

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

装饰者模式

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

同时继承父类,组合子类

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

相关推荐
charlie11451419127 分钟前
深入理解Qt的SetWindowsFlags函数
开发语言·c++·qt·原理分析
呜喵王阿尔萨斯34 分钟前
编程中的英语
c语言·c++
whoarethenext1 小时前
使用 C++/Faiss 加速海量 MFCC 特征的相似性搜索
开发语言·c++·faiss
向阳@向远方3 小时前
第二章 简单程序设计
开发语言·c++·算法
Mr_Xuhhh3 小时前
信号与槽的总结
java·开发语言·数据库·c++·qt·系统架构
liulilittle3 小时前
VGW 虚拟网关用户手册 (PPP PRIVATE NETWORK 基础设施)
开发语言·网络·c++·网关·智能路由器·路由器·通信
ruanjiananquan994 小时前
c,c++语言的栈内存、堆内存及任意读写内存
java·c语言·c++
持梦远方5 小时前
C 语言基础入门:基本数据类型与运算符详解
c语言·开发语言·c++
江理不变情5 小时前
图像质量对比感悟
c++·人工智能
apocelipes6 小时前
记一次ADL导致的C++代码编译错误
c++·开发工具和环境