Head First 设计模式——chapter3 装饰者模式C++实现

设计原则:

开闭原则: 对扩展开放,对修改关闭。

使得设计具有弹性可以应对改变,可以接受新的功能来应对改变需求。不需要每个地方都遵循,而是在设计最有可能改变的地方应用开闭原则。

eg: 观察者模式,通过加入新的观察者,可以扩展主题对象,而不需向主题中添加代码。

装饰者模式:

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

装饰类继承自超类,继承是为了有正确的类型,而非继承超类的行为。

#include<iostream>
#include<vector>
#include<algorithm>
#include <string>
#include <memory>

//饮料抽象类
class Beverage {
public:
	virtual ~Beverage() {};
	virtual std::string getDescription() = 0;
	virtual double cost() = 0;
protected:
	std::string description;
	
};
//调料装饰者类
class Condimentecorator :public Beverage {
public:
	virtual ~Condimentecorator() {};
	virtual std::string getDescription() = 0;
};

//espresso 饮料类
class Espresso :public Beverage {
public:
	Espresso() :Beverage()
	{
		description = "Espresso";
	}
	std::string getDescription() { return description; }
	double cost() 
	{
		return 1.99;
	}
};

//houseblend 饮料类
class HouseBlend :public Beverage {
public:
	HouseBlend() :Beverage()
	{
		description = "HouseBlend";
	}
	std::string getDescription() { return description; }
	double cost() 
	{
		return 0.89;
	}
};

//DarkRoast 饮料类
class DarkRoast :public Beverage {
public:
	DarkRoast() :Beverage()
	{
		description = "DarkRoast";
	}
	std::string getDescription() { return description; }
	double cost() 
	{
		return 0.99;
	}
};

//Decat 饮料类
class Decat :public Beverage {
public:
	Decat() :Beverage()
	{
		description = "Decat";
	}
	std::string getDescription() { return description; }
	double cost()
	{
		return 1.05;
	}
};

//Mocha调料装饰者
class Mocha :public Condimentecorator {

public:
	Mocha(std::shared_ptr<Beverage> be) :Condimentecorator(), beverage(be) {}
	std::string getDescription() 
	{
		return (beverage->getDescription() + " Mocha");
	}
	double cost()
	{
		return 0.2 + beverage->cost();
	}

public:
	std::shared_ptr<Beverage> beverage;
};

//Soy调料装饰者
class Soy :public Condimentecorator {
public:
	Soy(std::shared_ptr<Beverage> be):Condimentecorator(),beverage(be){}
	std::string getDescription()
	{
		return (beverage->getDescription() + " Soy");
	}
	double cost()
	{
		return 0.15 + beverage->cost();
	}
public:
	std::shared_ptr<Beverage> beverage;
};

//Whip调料装饰者
class Whip :public Condimentecorator {
public:
	Whip(std::shared_ptr<Beverage> be) :Condimentecorator(), beverage(be) {}
	std::string getDescription()
	{
		return (beverage->getDescription() + " Whip");
	}
	double cost()
	{
		return 0.10 + beverage->cost();
	}
public:
	std::shared_ptr<Beverage> beverage;
};

int main()
{
	std::shared_ptr<Beverage> beverage (new Espresso());
	std::cout << beverage->getDescription()<<" costs: "<<beverage->cost() << std::endl;

	std::shared_ptr<Beverage> beverage2(new DarkRoast());
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Mocha(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Mocha(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Whip(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;
	auto it = new Whip(beverage2);
	std::cout << it->cost() << " " << it->getDescription() << std::endl;
	std::cout << it->beverage->cost() << " " << it->beverage->getDescription() << std::endl;
	



	/*
	  Beverage *beverage3 = new HouseBlend();
    beverage3 = new Soy(beverage3);
    beverage3 = new Mocha(beverage3);
    beverage3 = new Whip(beverage3);
    cout << beverage3->getDescription() << " $" << beverage3->cost() << endl;
*/
	system("pause");
}

代码实现参考自:HeadFirst设计模式之装饰者模式(C++实现)_Xavier丶Zeng的博客-CSDN博客

增加大中小杯的概念:

#include<iostream>
#include<vector>
#include<algorithm>
#include <string>
#include <memory>

enum m_Size { tall,grande,venti };
//饮料抽象类
class Beverage {
public:
	Beverage(m_Size m=m_Size::grande):size(m){}
	virtual ~Beverage() {};
	virtual std::string getDescription() = 0;
	virtual double cost() = 0;
	void setSize(m_Size s) { size = s; }
	m_Size getSize() { return size; }
protected:
	std::string description;
	m_Size size;
};
//调料装饰者类
class Condimentecorator :public Beverage {
public:
	Condimentecorator(m_Size m):Beverage(m){}
	virtual ~Condimentecorator() {};
	virtual std::string getDescription() = 0;
};

//espresso 饮料类
class Espresso :public Beverage {
public:
	Espresso(m_Size s) :Beverage(s)
	{
		description = "Espresso";
	}
	std::string getDescription() { return (description+" "+std::to_string(getSize())); }
	double cost()
	{
		return 1.99;
	}
};

//houseblend 饮料类
class HouseBlend :public Beverage {
public:
	HouseBlend(m_Size s) :Beverage(s)
	{
		description = "HouseBlend";
	}
	std::string getDescription() { return (description + " " + std::to_string(getSize())); }
	double cost()
	{
		return 0.89;
	}
};

//DarkRoast 饮料类
class DarkRoast :public Beverage {
public:
	DarkRoast(m_Size s) :Beverage(s)
	{
		description = "DarkRoast";
	}
	std::string getDescription() { return (description + " " + std::to_string(getSize())); }
	double cost()
	{
		return 0.99;
	}
};

//Decat 饮料类
class Decat :public Beverage {
public:
	Decat(m_Size s) :Beverage(s)
	{
		description = "Decat";
	}
	std::string getDescription() { return (description + " " + std::to_string(getSize())); }
	double cost()
	{
		return 1.05;
	}
};

//Mocha调料装饰者
class Mocha :public Condimentecorator {

public:
	
	Mocha(std::shared_ptr<Beverage> be) :Condimentecorator(be->getSize()), beverage(be) {}
	std::string getDescription()
	{
		return (beverage->getDescription() + " Mocha");
	}

	double cost()
	{
		double tmp= 0.2 + beverage->cost();
		if (beverage->getSize() == m_Size::tall)
			tmp += 0.1;
		else if (beverage->getSize() == m_Size::grande)
			tmp += 0.15;
		else if (beverage->getSize() == m_Size::venti)
			tmp += 0.2;

		return tmp;
	}

public:
	std::shared_ptr<Beverage> beverage;
};

//Soy调料装饰者
class Soy :public Condimentecorator {
public:
	Soy(std::shared_ptr<Beverage> be) :Condimentecorator(be->getSize()), beverage(be) {}
	std::string getDescription()
	{
		return (beverage->getDescription() + " Soy");
	}
	double cost()
	{
		double tmp= 0.15 + beverage->cost();
		if (beverage->getSize() == m_Size::tall)
			tmp += 0.1;
		else if (beverage->getSize() == m_Size::grande)
			tmp += 0.15;
		else if (beverage->getSize() == m_Size::venti)
			tmp += 0.2;

		return tmp;
	}
public:
	std::shared_ptr<Beverage> beverage;
};

//Whip调料装饰者
class Whip :public Condimentecorator {
public:
	Whip(std::shared_ptr<Beverage> be) :Condimentecorator(be->getSize()), beverage(be) {}
	std::string getDescription()
	{
		return (beverage->getDescription() + " Whip");
	}
	double cost()
	{
		double tmp= 0.10 + beverage->cost();
		if (beverage->getSize() == m_Size::tall)
			tmp += 0.1;
		else if (beverage->getSize() == m_Size::grande)
			tmp += 0.15;
		else if (beverage->getSize() == m_Size::venti)
			tmp += 0.2;

		return tmp;
	}
public:
	std::shared_ptr<Beverage> beverage;
};

int main()
{
	
	std::shared_ptr<Beverage> beverage2(new DarkRoast(m_Size::venti));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Mocha(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Mocha(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	beverage2 = std::shared_ptr<Beverage>(new Whip(beverage2));
	std::cout << beverage2->getDescription() << " costs: " << beverage2->cost() << std::endl;

	//auto it = new Whip(beverage2);
	//std::cout << it->cost() << " " << it->getDescription() << std::endl;
	//std::cout << it->beverage->cost() << " " << it->beverage->getDescription() << std::endl;




	/*
	  Beverage *beverage3 = new HouseBlend();
	beverage3 = new Soy(beverage3);
	beverage3 = new Mocha(beverage3);
	beverage3 = new Whip(beverage3);
	cout << beverage3->getDescription() << " $" << beverage3->cost() << endl;
*/
	system("pause");
}

注意 每个调料在构造函数初始化时,要向父类构造函数中传入当前的杯型,否则会按照默认杯型操作,造成结算价格错误。

优点:

(1)装饰者和被装饰者有相同的超类型,所以在任何需要原始对象(被包装)的场合,都可以用装饰过的对象替代。

(2)可以用一个或多个装饰者包装一个对象

(3)装饰者可以在被装饰者的行为前/后,加上自己的行为,以达到特定的目的。

(4)可以在运行时,不限量地用喜欢的装饰者来装饰对象。

缺点:

装饰者模式,会造成设计中有大量的小类,数量过多,可能会造成使用此API程序员的困扰。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值