最近在学习设计模式中的装饰者模式,前面我的一篇博客“装饰者模式及C++代码实现”已经比较深入地解析了“什么叫装饰者模式”,以及在面向对象系统的设计中运用“装饰者模式”有什么妙处! 装饰者模式通过组合的方式提供了一种给类增加职责的方法!
在下面我写的咖啡店收银系统中就恰当地运用了“装饰者模式”的思想。 假设现在有一个咖啡店里面有四种咖啡系列:黑咖啡,白咖啡,加味咖啡,拿铁咖啡。这四种咖啡中每一种咖啡都分为大杯和中杯还有小杯三种型号,并且每对应的一种型号的咖啡都有一个自定的价格! 现在为了满足顾客对同一种咖啡系列的多种口味的需求,那么作为店主我把每一种咖啡都用奶油,糖和牛奶三种调料任意组合,每一个咖啡系列派生出八种咖啡。 这样用三种调料任意组合调制出来的咖啡每一种价格是不一样的!
现在的问题是面对上面这种情况,你会怎么设计这个系统?? 有人会说用继承的方法不就行了嘛! 但是本人认为对于这种情况用继承的方法来解决的话,有一个非常不好的问题!那就是对于每一种咖啡系列都得作为一个基类,然后分别从每一种咖啡系列的基类下派生出八个子类! 这样做的话要建立的类是比较多的!每一种咖啡系类下面就有八个子类,那么四种咖啡系列的话,光是子类就得有32个!这样做系统的复杂性无疑是提高了很多,不利于以后系统的维护! 此外,这样做的一个最严重的问题是:系统的扩展性比较差! 假如现在咖啡店要增加一种咖啡系列并且还要增加一种调味品沙糖,那这个时候如果你以前是按照继承的方法设计的系统的话,你就该是很头痛了!尤其是要增加一种调味品沙糖!增加了一种砂糖的话,你前面的所有咖啡系统下面的子类都要更改,每个子类都要更改,这样的话你首先就要更改前面四种咖啡下面的每一个子类,你总共要更改32个子类! 剩下的增加的一个咖啡系统下面的子类都要你自己一字一句去编写! 显然这样做的话,你的工作量是非常大的!说的夸张点你的效率相对于高手来说是个负数!!而一开始我就用“装饰者模式”来架构整个系统的话,现在弄起来的话就轻松多了,我把每个一个咖啡系列看做是一个被装饰类,把每一种调料看做是一种装饰咖啡的装饰类! 当我要增加一种咖啡系类或者增加一种调味品的时候,我只不过是增加一个被装饰类或者增加一个装饰类而已! 这样对以前编写好的整个系统的影响是很小的,也就是说系统的耦合性比较的弱,模块与模块之间的独立性比较强! 类的扩展性非常的好! 这是非常符合面向对象系统设计所追求的“高内聚”,“低耦合”的目标的!
#include<iostream>
#include<string>
using namespace std;
//抽象类,咖啡
class coffee
{
public:
virtual float dabei_cost() = 0;
virtual float zhongbei_cost() = 0;
virtual float xiaobei_cost() = 0;
};
//具体类,黑咖啡
class black_coffee :public coffee
{
public:
virtual float dabei_cost() //大杯价格
{
return 15.0;
}
virtual float zhongbei_cost()//中杯价格
{
return 10.0;
}
virtual float xiaobei_cost()//小杯价格
{
return 5.0;
}
};
//具体类,白咖啡
class white_coffee :public coffee
{
public:
virtual float dabei_cost()//大杯价格
{
return 18.0;
}
virtual float zhongbei_cost()//中杯价格
{
return 14.0;
}
virtual float xiaobei_cost()//小杯价格
{
return 10.0;
}
};
//具体类,加味咖啡
class flavored_coffee :public coffee
{
public:
virtual float dabei_cost()//大杯价格
{
return 20.0;
}
virtual float zhongbei_cost()//中杯价格
{
return 15.0;
}
virtual float xiaobei_cost()//小杯价格
{
return 10.0;
}
};
//具体类,拿铁咖啡
class caffelatte :public coffee
{
public:
virtual float dabei_cost()//大杯价格
{
return 25.0;
}
virtual float zhongbei_cost()//中杯价格
{
return 20.0;
}
virtual float xiaobei_cost()//小杯价格
{
return 15.0;
}
};
//装饰者类,给咖啡加入若干种调味品
class Add_Condiment :public coffee
{
public:
void Decorate(coffee*cof)
{
this->cof = cof;
}
public:
virtual float dabei_cost()
{
return (cof->dabei_cost());
}
virtual float zhongbei_cost()
{
return(cof->zhongbei_cost());
}
virtual float xiaobei_cost()
{
return(cof->xiaobei_cost());
}
protected:
coffee*cof;
};
//给咖啡加牛奶
class has_milk :public Add_Condiment
{
public:
float with_milk()
{
return 1.0;
}
public:
virtual float dabei_cost()
{
return(with_milk() + (Add_Condiment::dabei_cost()));
}
virtual float zhongbei_cost()
{
return(with_milk() + (Add_Condiment::zhongbei_cost()));
}
virtual float xiaobei_cost()
{
return(with_milk() + (Add_Condiment::xiaobei_cost()));
}
};
//给咖啡加糖
class has_sugar :public Add_Condiment
{
public:
float with_sugar()
{
return 0.5;
}
public:
virtual float dabei_cost()
{
return(with_sugar() + (Add_Condiment::dabei_cost()));
}
virtual float zhongbei_cost()
{
return(with_sugar() + (Add_Condiment::zhongbei_cost()));
}
virtual float xiaobei_cost()
{
return(with_sugar() + (Add_Condiment::xiaobei_cost()));
}
};
//给咖啡加奶油
class has_cream :public Add_Condiment
{
public:
float with_cream()
{
return 3.0;
}
public:
virtual float dabei_cost()
{
return(with_cream() + (Add_Condiment::dabei_cost()));
}
virtual float zhongbei_cost()
{
return(with_cream() + (Add_Condiment::zhongbei_cost()));
}
virtual float xiaobei_cost()
{
return(with_cream() + (Add_Condiment::xiaobei_cost()));
}
};
int main(void)
{
cout << " 欢迎光临本店! " << endl;
cout << "*******************************请选择咖啡系列********************************" << endl;
cout << " ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏" << endl;
cout << " ▕ 1.黑咖啡系列 2.白咖啡系列 3.加味咖啡系列 4.拿铁咖啡系列 ▏" << endl;
cout << " ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏" << endl;
int choise;
cout << " 请输入数字选择对应的咖啡系列:";
cin >> choise;
switch (choise)
{
case 1:
{
cout << " ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏" << endl;
cout << " ▕ 黑咖啡系列有以下种类,请选择: ▏" << endl;
cout << " ▕ 1.黑咖啡(纯) 2.黑咖啡+牛奶 3.黑咖啡+糖 4.黑咖啡+奶油 ▏" << endl;
cout << " ▕ 5.黑咖啡+牛奶+糖 6.黑咖啡+牛奶+奶油 7.黑咖啡+糖+奶油 ▏" << endl;
cout << " ▕ 8.黑咖啡+牛奶+糖+奶油 ▏" << endl;
cout << " ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏" << endl;
cout << " 请输入数字选择您想要的咖啡:";
int a;
cin >> a;
switch (a)
{
case 1:
cout << " 请选择黑咖啡的型号:" << endl;
cout << " 1.大杯 2.中杯 3.小杯" << endl;
cout << " 请输入对应的数字选择您想要的型号:";
int a1;
cin >> a1;
switch (a1)
{
case 1:
{
coffee*c1 = new black_coffee;
cout << endl << " 请付" << c1->dabei_cost() << "元!" << "谢谢!" << endl;
delete c1; break;
}
case 2:
{
coffee*c2 = new black_coffee;
cout << endl << " 请付" << c2->zhongbei_cost() << "元!" << "谢谢!" << endl;
delete c2; break;
}
case 3:
{
coffee*c3 = new black_coffee;
cout << endl << " 请付" << c3->xiaobei_cost() << "元!" << "谢谢!" << endl;
delete c3; break;
}
default:printf("输入有误!\n");
}break;
case 2:
cout << " 请选择黑咖啡+牛奶的型号:" << endl;
cout << " 1.大杯 2.中杯 3.小杯" << endl;
cout << " 请输入对应的数字选择您想要的型号:";
int a2;
cin >> a2;
switch (a2)
{
case 1:
{
coffee*b1 = new black_coffee;
Add_Condiment*b2 = new has_milk;
b2->Decorate(b1);
cout << endl << " 请付" << b2->dabei_cost() << "元!" << "谢谢!" << endl;
delete b1; delete b2; break;
}
case 2:
{
coffee*b3 = new black_coffee;
Add_Condiment*b4 = new has_milk;
b4->Decorate(b3);
cout << endl << " 请付" << b4->zhongbei_cost() << "元" << "谢谢!" << endl;
delete b3; delete b4; break;
}
case 3:
{
coffee*b5 = new black_coffee;
Add_Condiment*b6 = new has_milk;
b6->Decorate(b5);
cout << endl << " 请付" << b6->xiaobei_cost() << "元" << "谢谢!" << endl;
delete b5; delete b6; break;
}
default:printf("输入有误!\n");
}break;
case 3:
cout << " 请选择黑咖啡+糖的型号:" << endl;
cout << " 1.大杯 2.中杯 3.小杯" << endl;
cout << " 请输入对应的数字选择您想要的型号:";
int a3;
cin >> a3;
switch (a3)
{
case 1:
{
coffee *d1 = new black_coffee;
Add_Condiment*d2 = new has_sugar;
d2->Decorate(d1);
cout << endl << " 请付" << d2->dabei_cost() << "元!" << "谢谢!" << endl;
delete d1; delete d2; break;
}
case 2:
{
coffee *d3 = new black_coffee;
Add_Condiment *d4 = new has_sugar;
d4->Decorate(d3);
cout << endl << " 请付" << d4->zhongbei_cost() << "元!" << "谢谢!" << endl;
delete d3; delete d4; break;
}
case 3:
{
coffee*d5 = new black_coffee;
Add_Condiment*d6 = new has_sugar;
d6->Decorate(d5);
cout << endl << " 请付" << d6->xiaobei_cost() << "元!" << "谢谢!" << endl;
delete d5; delete d6; break;
}
default:printf("输入有误!\n");
}break;
case 4:
cout << " 请选择黑咖啡+奶油的型号:" << endl;
cout << " 1.大杯 2.中杯 3.小杯" << endl;
cout << " 请输入对应的数字选择您想要的型号:";
int a4;
cin >> a4;
switch (a4)
{
case 1:
{
coffee *e1 = new black_coffee;
Add_Condiment*e2 = new has_cream;
e2->Decorate(e1);
cout << endl << " 请付" << e2->dabei_cost() << "元" << "谢谢!" << endl;
delete e1; delete e2; break;
}
case 2:
{
coffee *e3 = new black_coffee;
Add_Condiment*e4 = new has_cream;
e4->Decorate(e3);
cout << endl << " 请付" << e4->zhongbei_cost() << "元" << "谢谢!" << endl;
delete e3; delete e4; break;
}
case 3:
{
coffee *e5 = new black_coffee;
Add_Condiment*e6 = new has_cream;
e6->Decorate(e5);
cout << endl << " 请付" << e6->xiaobei_cost() << "元" << "谢谢!" << endl;
delete e5; delete e6; break;
}
default:printf("输入有误!\n");
}break;
case 5:
cout << " 请选择黑咖啡+牛奶+糖的型号:" << endl;
cout << " 1.大杯 2.中杯 3.小杯" << endl;
cout << " 请输入对应的数字选择您想要的型号:";
int a5;
cin >> a5;