• 设计模式C++实现——装饰者模式


    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/walkerkalr/article/details/28633123

    模式定义:

            装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

            装饰者和被装饰者有同样的超累类型。

            能够用一个或多个装饰者包装一个对象。

            既然装饰者和被装饰者对象有同样的超累类型,所以在不论什么须要原始对象(被包装的)的场合,能够用装饰过的对象取代它。

            装饰者能够托付被装饰者的行为之前与或之后,加上自己的行为,以达到特定的目的。

            对象能够在不论什么时候被装饰,所以能够在执行时动态地、不限量地用你喜欢的装饰者来装饰对象。

    模式结构:

    举例:

            购买咖啡时,能够在当中增加各种调料,例如:蒸奶(Steamed Milk)。豆浆(Soy)。摩卡(Mocha)或覆盖奶泡。

    咖啡馆会依据所增加的调料收取不同的费用。

            解决方法:我们以饮料为主体。然后在执行时以调料来装饰饮料。例如说顾客想要摩卡和奶泡深焙咖啡。那么,要做的是:拿一个深焙咖啡(DarkRoast)对象,以摩卡(Mocha)对象装饰它。以奶泡对象装饰它,调用cost()方法。并依赖托付将调料的价钱加上去。

    UML设计:

    编程实现及执行结果:

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Beverage
    {
    public:
    	Beverage(string str = "Unknow Beverage")
    		:description(str){}
    
    	virtual string getDescription()
    	{
    		return description;
    	}
    
    	virtual double cost(){return 0;}
    
    private:
    	string description;
    };
    
    class CondimentDecorator : public Beverage
    {
    public:
    	string getDescription(){return "";}
    };
    
    class Espresso : public Beverage
    {
    public:
    
    	Espresso():Beverage("Espresso"){}
    
    	double cost()
    	{
    		return 1.99;
    	}
    };
    
    class HouseBlend : public Beverage
    {
    public:
    	HouseBlend():Beverage("HouseBlend Coffee"){}
    
    	double cost()
    	{
    		return 0.89;
    	}
    };
    
    class Mocha : public CondimentDecorator
    {
    public:
    	Mocha(Beverage* beve)
    	{
    		beverage = beve;
    	}
    	
    	string getDescription()
    	{
    		return beverage->getDescription()+", Mocha";
    	}
    
    	double cost()
    	{
    		return 0.20 + beverage->cost();
    	}
    private:
    	Beverage* beverage;
    };
    
    class Whip : public CondimentDecorator
    {
    public:
    	Whip(Beverage* beve)
    	{
    		beverage = beve;
    	}
    	
    	string getDescription()
    	{
    		return beverage->getDescription()+", Whip";
    	}
    
    	double cost()
    	{
    		return 0.15 + beverage->cost();
    	}
    private:
    	Beverage* beverage;
    };
    int main()
    {
    	Beverage* pBeverage = new Espresso();
    	cout << pBeverage->getDescription() << " $" << pBeverage->cost() <<endl;
    
    	Beverage* pBeverage2 = new Espresso();
    	pBeverage2 = new Mocha(pBeverage2);
    	pBeverage2 = new Mocha(pBeverage2);
    	cout << pBeverage2->getDescription() << " $" << pBeverage2->cost() <<endl;
    
    	pBeverage2 = new Whip(pBeverage2);
    	cout << pBeverage2->getDescription() << " $" << pBeverage2->cost() <<endl;
    	
    	return 0;
    }


            执行结果:

    Espresso$1.99

    Espresso,Mocha, Mocha $2.39

    Espresso,Mocha, Mocha, Whip $2.54

    请按随意键继续. . .

            这样就能够是不同饮料增加不同的配料,而不用改动源码。而且能够增加新的配料类型和饮料类型。

    设计原则的应用:

            设计原则5:类应该对外扩展。对改动关闭。如装饰者模式中,我们的目标是同意类easy扩展,在不改动现有代码的情况下。就可搭配新的行为。

             參考:Head First设计模式
  • 相关阅读:
    线程池中的scheduleAtFixedRate scheduleWithFixedDelay区别
    几道MySQL问题
    【SQL server 2012】复制数据库到另一台机器上
    LeetCode 98. 验证二叉搜索树
    深度学习知识点
    Graph Network Notes
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    剑指 Offer 29. 顺时针打印矩阵
    LeetCode 54. 螺旋矩阵
    LeetCode 50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10756775.html
Copyright © 2020-2023  润新知