状态模式
最后更新于:2022-04-01 20:29:41
## 模式定义
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c54593859f1.jpg)
Context:
环境定义客户感兴趣的接口
维护一个ConcreteState子类的实例,这个实例定义当前状态
State:
定义一个接口封装与Context的一个特定状态相关的行为
ConcreteState subclasses:
每一子类实现一个与Context的一个状态相关的行为
## 举例:
一个工人一天的时间分为上班,睡觉,干其他事情三个时间段。我们可以用状态模式来表示一天中在干什么事情。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c54593ddc27.jpg)
## 编程实现及执行结果:
~~~
#include
using namespace std;
class Worker; //类的前置声明
//状态类
class State
{
public:
virtual void doing(Worker* w){}
};
//工作状态
class WorkingState: public State
{
public:
void doing(Worker* worker);
};
//休息状态
class SleepingState: public State
{
public:
void doing(Worker* worker);
};
//其他状态
class OtherState : public State
{
public:
void doing(Worker* worker);
};
//工人类
class Worker
{
public:
Worker()
{
state = new WorkingState();
}
void setState(State* stat)
{
state = stat;
}
double getHour()
{
return hour;
}
void setHour(double hou)
{
hour = hou;
}
void requestDoing()
{
state->doing(this);
}
private:
State* state;
double hour;
};
//各个状态doing方法的实现
void WorkingState::doing(Worker* worker)
{
if(worker->getHour() > 8 && worker->getHour() < 16)
cout << "WorkingState!" << endl;
else
{
worker->setState(new OtherState());
worker->requestDoing();
}
}
void SleepingState::doing(Worker* worker)
{
if(worker->getHour() >= 21 || worker->getHour() < 5)
cout << "SleepingState!" << endl;
else
{
worker->setState(new OtherState());
worker->requestDoing();
}
}
void OtherState::doing(Worker* worker)
{
if((worker->getHour() >= 5 && worker->getHour() < 8)
|| (worker->getHour() >= 16 && worker->getHour() < 21))
cout << "SleepingState!" << endl;
else if(worker->getHour() >= 21 || worker->getHour() < 5)
{
worker->setState(new SleepingState());
worker->requestDoing();
}
else
{
worker->setState(new WorkingState());
worker->requestDoing();
}
}
//客户代码
int main()
{
Worker* pWorker = new Worker();
pWorker->setHour(24);
cout << "time 24" << endl;
pWorker->requestDoing();
pWorker->setHour(11.5);
cout << "time 11.5" << endl;
pWorker->requestDoing();
pWorker->setHour(19);
cout << "time 19" << endl;
pWorker->requestDoing();
delete pWorker;
return 0;
}
~~~
执行结果:
**time24**
**SleepingState!**
**time11.5**
**WorkingState!**
**time19**
**SleepingState!**
**请按任意键继续. . .**
';
组合模式
最后更新于:2022-04-01 20:29:38
## 模式定义:
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
这个模式能够创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组。通过菜单和项放在相同结构中,我们创建了一个“整体/部分”层次结构,即由菜单和菜单项组成的对象树。使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c54591e2a52.jpg)
**Component:**
为组合中的对象声明接口;
在适当情况下实现所有类共有接口的缺省行为;
声明一个接口用于访问管理Component的子组件
在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它
**Leaf:**
在组合中表示叶节点对象,叶节点没有子节点,并定义其行为
**Composite:**
定义有子部件的那些部件的行为
存储子部件
实现与子部件有关的操作
**Client:**
通过Component接口操作组合件和个别对象。
## 举例:
在迭代器例子中,我们希望在午餐餐单中增加一份跌点餐单,也就是说希望能让甜点餐单变成午餐餐单的一个元素。
我们可以用组合模式解决这个问题:一开始我们创建一个组件接口作为餐单和菜单项的共同接口,让我们能够用统一的做法来处理菜单和菜单项。换句话说,我们可以针对菜单或菜单项调用相同的方法。然后实现菜单项和组合菜单组件,以及他们各自的方法。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c545923b19a.jpg)
## 编程实现及执行结果:
~~~
#include
#include
#include
';
-
#include
迭代器模式
最后更新于:2022-04-01 20:29:36
## 模式定义
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c545916c8cc.jpg)
Iterator:迭代器定义访问和遍历元素的接口
ConcreteIterator:具体迭代器实现迭代器接口;对该聚合遍历时跟踪当前位置
Aggregate:聚合定义创建相应的迭代器对象接口
ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。
## 举例:
煎饼屋和午餐店合并后需要定制一份新的餐单,但由于煎饼屋的原菜单是用链表实现,而午餐点原菜单是用数组实现(他们的定义如下所示),所以打印新餐单的时候需要分别循环遍历原餐单中的菜单项。
~~~
//菜单项类
class MenuItem
{
public:
MenuItem(){}
MenuItem(string na, string descrip, double pric)
{
name = na;
description = descrip;
price = pric;
}
string getName()
{
return name;
}
string getDescription()
{
return description;
}
double getPrice()
{
return price;
}
private:
string name;
string description;
double price;
};
//煎饼屋餐单类
class PancakeHouseMenu
{
public:
PancakeHouseMenu()
{
addItem("K&B'S Breakfase","pacakes with eggs",2.99);
addItem("Buleberry Breakfase","pacakes with buleberries",3.99);
}
void addItem(string na, string descrip, double ric)
{
MenuItem menuItem(na,descrip,ric);
menuItems.push_back(menuItem);
}
list
';
模板方法模式
最后更新于:2022-04-01 20:29:34
## 模式定义:
模板方法模式在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板就是一个方法。更具体的说,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类实现。这可以确保算法的结果保持不变,同时由子类提供部分实现。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c54590dbd73.jpg)
## 举例:
泡咖啡和泡茶步骤与基本相同,定义咖啡和茶的类如下:
~~~
class Coffee
{
public:
void prepareRecipe()
{
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
void boilWater()
{
cout << "Boiling water" << endl;
}
void brewCoffeeGrinds()
{
cout << "Dripping Coffee through filter" << endl;
}
void pourCup()
{
cout << "Pouring into cup" <
using namespace std;
//定义咖啡因基类
class CaffeineBeverage
{
public:
void prepareRecipe()
{
boilWater();
brew();
pourInCup();
addCondiments();
}
void boilWater()
{
cout << "Boiling water" << endl;
}
void pourInCup()
{
cout << "Pouring into cup" <
';
外观模式
最后更新于:2022-04-01 20:29:32
## 模式定义:
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c545909cbf5.jpg)
## 举例:
构造一个家庭影院,当启动watchMovie方法时可以看电影,当使用endMovie时关闭电影。
## 编程实现及执行结果:
~~~
#include
using namespace std;
//组件类
class Amplifier
{
public:
void on()
{
cout << "Amplifier on" << endl;
}
void off()
{
cout << "Amplifier off" << endl;
}
};
class Tuner
{
public:
void on()
{
cout << "Tuner on" << endl;
}
void off()
{
cout << "Tuner off" << endl;
}
};
class DvdPlayer
{
public:
void on()
{
cout << "DvdPlayer on" << endl;
}
void off()
{
cout << "DvdPlayer off" << endl;
}
};
class Screen
{
public:
void on()
{
cout << "Screen on" << endl;
}
void off()
{
cout << "Screen off" << endl;
}
};
//家庭影院
class HomeTheaterFacade
{
public:
//统一接口
void watchMovie()
{
amp.on();
tuner.on();
dvd.on();
screen.on();
}
void endMovie()
{
amp.off();
tuner.off();
dvd.off();
screen.off();
}
HomeTheaterFacade(Amplifier am,
Tuner tune,
DvdPlayer dv,
Screen scree)
{
amp = am;
tuner = tune;
dvd = dv;
screen = scree;
}
//~HomeTheaterFacade(){}
private:
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
Screen screen;
};
//客户代码
int main()
{
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
Screen screen;
HomeTheaterFacade homeTheaterFacade(amp,tuner,dvd,screen);;
homeTheaterFacade.watchMovie();
homeTheaterFacade.endMovie();
return 0;
}
~~~
执行结果:
**Amplifieron**
**Tuneron**
**DvdPlayeron**
**Screenon**
**Amplifieroff**
**Tuneroff**
**DvdPlayeroff**
**Screenoff**
**请按任意键继续. . .**
## 设计原则:
最少知识原则:只和你的密友谈话
';
适配器模式
最后更新于:2022-04-01 20:29:29
## 模式定义:
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适配器可以分为类适配器和对象适配器。
类适配器使用多重继承对一个接口与另一个接口进行匹配。
对象适配器依赖于对象组合。
客户使用适配器的过程:
1. 客户通过目标接口调用适配器的方法对适配器发出请求。
2. 适配器使用被适配者接口把请求转换成被施培者的一个或多个调用接口
3. 客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用。
## 模式结构:
类适配器
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458ff153e.jpg)
对象适配器
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5459021a1f.jpg)
## 举例:
现在假设你缺少鸭子对象(叫声为Quack,飞行输出”I’m flying !”),想用一些火鸡对象(叫声为”Gobble gobble” 飞行输出”I’m flying a short distance!”)来冒充。显而易见,因为火鸡的接口(行为)不同,所以我们不能公然拿来使用。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5459056854.jpg)
## 编程实现及执行结果:
~~~
#include
using namespace std;
//定义鸭子类
class Duck
{
public:
virtual void quack(){};
virtual void fly(){};
};
//定义绿头鸭
class MallardDuck : public Duck
{
public:
void quack()
{
cout << "Quack" << endl;
}
void fly()
{
cout << "I'm flying" << endl;
}
};
//定义火鸡
class Turkey
{
public:
virtual void gobble(){}
virtual void fly(){}
};
//定义野火鸡
class WildTurkey : public Turkey
{
public:
void gobble()
{
cout << "Gobble gobble" << endl;
}
void fly()
{
cout << "I'm flying a short distance" << endl;
}
};
//定义火鸡适配器
class TurkeyAdapter : public Duck
{
public:
TurkeyAdapter(Turkey* tur):turkey(tur){}
void quack()
{
turkey->gobble();
}
void fly()
{
turkey->fly();
}
private:
Turkey* turkey;
};
//客户代码
int main()
{
Duck* duck = new MallardDuck();
duck->quack();
duck->fly();
Duck* turkeyAdapter = new TurkeyAdapter(new WildTurkey());
turkeyAdapter->quack();
turkeyAdapter->fly();
return 0;
}
~~~
执行结果:
**Quack**
**I'mflying**
**Gobblegobble**
**I'mflying a short distance**
**请按任意键继续. . .**
## 适配器和装饰者模式比较:
适配器:将一个接口转成另一个接口。包装某些对象,让它们的接口看起来不像自己而像别的东西。
装饰者:不改变接口,但加入责任。将对象包装起来,让新行为加入类中。
';
命令模式
最后更新于:2022-04-01 20:29:27
## 模式定义:
命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
命令对象将动作和接受者包进对象中,这个对象只暴露一个execute()方法。
当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458f5e3ea.jpg)
## 举例:
遥控器上有一个插槽,可以放上不同的装置,然后用按钮控制。我们这里放置电灯,并有开和关按钮。可以命令模式实现。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458fc8b65.jpg)
其中,RemoteControl为遥控器,LightOnCommand为开灯请求对象,LightOffCommand为关灯请求对象,他们继承自基类Command,这样设计可以使插槽在以后防止其他的装置。
## 编程实现及执行结果:
~~~
#include
using namespace std;
//电灯类
class Light
{
public:
void on()
{
cout << "Light on !" << endl;
}
void off()
{
cout << "Light off !" << endl;
}
};
//命令类
class Command
{
public:
virtual void execute(){}
};
//具体命令类
class LigthOnCommand : public Command
{
public:
LigthOnCommand(Light* lig):light(lig){}
//execute方法
void execute()
{
light->on();
}
private:
Light* light;
};
class LigthOffCommand : public Command
{
public:
LigthOffCommand(Light* lig):light(lig){}
void execute()
{
light->off();
}
private:
Light* light;
};
//遥控器类
class RemoteControl
{
public:
void setCommand(Command* command)
{
slot = command;
}
void buttonOn()
{
slot->execute();
}
private:
Command* slot;
};
//客户代码
int main()
{
RemoteControl lightOnControl;
RemoteControl lightOffControl;
Command* onCommand = new LigthOnCommand(new Light());
Command* offCommand = new LigthOffCommand(new Light());
lightOnControl.setCommand(onCommand);
lightOffControl.setCommand(offCommand);
lightOnControl.buttonOn();
lightOffControl.buttonOn();
return 0;
}
~~~
执行结果:
**Lighton !**
**Lightoff !**
**请按任意键继续. . .**
';
单例模式
最后更新于:2022-04-01 20:29:25
## 模式定义:
单例模式确保一个类只有一个实例,并提供一个全局访问点。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458f38c59.jpg)
## 单例模式编程实现及执行结果:
~~~
#include
using namespace std;
~~~
单例类
~~~
class Sigleton
{
public:
static Sigleton* getInstance(); //必须是static,否则无法调用getInstance
private:
Sigleton(){}
static Sigleton* uniqueInstance;
};
~~~
静态成员初始化
~~~
Sigleton* Sigleton::uniqueInstance = NULL;
~~~
成员函数实现
~~~
Sigleton* Sigleton::getInstance()
{
if(uniqueInstance == NULL)
{
uniqueInstance = new Sigleton();
}
return uniqueInstance;
}
~~~
客户代码
~~~
int main()
{
Sigleton* pSigleton1 = Sigleton::getInstance();
Sigleton* pSigleton2 = Sigleton::getInstance();
if(pSigleton1 == pSigleton2)
cout << "Sigleton Successful" << endl;
else
cout << "Sigleton failue" << endl;
return 0;
}
~~~
执行结果:
**Sigleton Successful**
**请按任意键继续. . .**
## 应用:创建Sigleton类的子类
我们应当考虑Sigleton的多个子类,而且应用必须决定使用哪一个子类。修改Sigleton方法如下:
单例基类
~~~
class Sigleton
{
public:
static Sigleton* getInstance(const char* name);
virtual void show(){cout << "Sigleton" << endl;}
protected: //基类构造函数访问权限位protected,使子类构造函数可以调用基类构造函数
Sigleton(){}
private:
static Sigleton* uniqueInstance;
};
';
Sigleton* Sigleton::uniqueInstance = NULL; Sigleton* Sigleton::getInstance(const char* name) { if(uniqueInstance == NULL) { if(strcmp(name,"SigletonA") == 0) { uniqueInstance = new SigletonA(); } else if(strcmp(name,"SigletonB") == 0) { uniqueInstance = new SigletonB(); } else { uniqueInstance = new Sigleton(); } } return uniqueInstance; } ~~~ A类子类 ~~~ class SigletonA : public Sigleton { //声明基类为友元,使其可以访问A类私有构造函数 friend class Sigleton; public: void show(){cout << "SigletonA" << endl;} private: SigletonA(){} }; ~~~ B子类 ~~~ class SigletonB : public Sigleton { friend class Sigleton; public: void show(){cout << "SigletonB" << endl;} private: SigletonB(){} }; ~~~ 客户代码 ~~~ int main() { Sigleton* pSigleton1 = Sigleton::getInstance("SigletonA"); Sigleton* pSigleton2 = Sigleton::getInstance("SigletonA"); Sigleton* pSigleton3 = Sigleton::getInstance("SigletonB"); Sigleton* pSigleton4 = Sigleton::getInstance("SigletonB"); if(pSigleton1 == pSigleton2) cout << "SigletonA Successful" << endl; else cout << "SigletonA failue" << endl; pSigleton1->show(); pSigleton3->show(); return 0; } ~~~ 执行结果: **SigletonA Successful** **SigletonA** **SigletonA** **请按任意键继续. . .**
抽象工厂模式
最后更新于:2022-04-01 20:29:23
## 模式定义:
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道实际产出的具体产品时什么。这样一来,客户就从具体的产品中被解耦了。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458ed08d4.jpg)
## 举例:
数据库访问程序设计,不同的数据库访问方式可能不一样,为了抽象对对不同数据库的访问,可以将数据库隐藏起来,提供统一的访问方式,用多态进行实现。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458f0df87.jpg)
## 编程实现及执行结果:
~~~
#include
using namespace std;
~~~
用户表接口
~~~
class IUser
{
public:
virtual void Insert() = 0;
virtual void GetUser() = 0;
};
~~~
SqlServer数据库访问User表
~~~
class SqlServerUser : public IUser
{
public:
void Insert()
{
cout<<"在SQL Server中给User表增加一条记录"<>choise;
switch(choise)
{
case 1:
pFactory= new SqlServerFactory(); //创建SqlServer访问的工厂
break;
case 2:
pFactory = new AccessFactory(); //创建Access访问的工厂
break;
}
//一致的操作
pUser = pFactory->CreateUser();
pDepartment= pFactory->CreateDepartment();
pUser->Insert();
pUser->GetUser();
pDepartment->Insert();
pDepartment->GetDepartment();
return 0;
}
~~~
执行结果如下:
**选择数据库: 2**
**在Access中给User表增加一条记录**
**在Access中User表获取一条记录**
**在Access中给Department表增加一条记录**
**在Access中Department获取一条记录**
**请按任意键继续. . .**
## 设计原则的应用:
设计原则4:为交互对象之间的耦合设计而努力
参考:[http://baike.baidu.com/view/1580269.htm?fr=aladdin](http://baike.baidu.com/view/1580269.htm?fr=aladdin)
Head First 设计模式
';
工厂方法模式
最后更新于:2022-04-01 20:29:20
## 模式定义:
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458e6ea3f.jpg)
Creator是一个类,它实现了所有操纵产品的方法,但不实现工厂方法。Creator的所有子类都必须实现工厂方法(factoryMethod()),以实际制造出产品。
所有的产品必须实现Product基类,这样一来使用这些产品的类就可以引用这个基类,而不是派生类。
## 举例:
披萨店希望能够开一些加盟店。经营者希望确保加盟店运营的质量,所以希望这些店都使用能经过实践考研的代码。问题在于每家加盟店都可能想要提供不同风味的披萨(比方说纽约,芝加哥,加州),这收到了开店地点及该地区披萨口味的影响。
解决办法:让每个区域风味的披萨工厂继承基类披萨工厂使披萨工厂的订单系统不变,然后创建自己风味的披萨。这样真正选购披萨类型,使用具体的披萨工厂决定的。
## 类图设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458e9ed77.jpg)
## 编程实现及执行结果:
~~~
#include
#include
#include
';
-
using namespace std;
~~~
首先创建Pizza类
~~~
class Pizza
{
public:
Pizza(string nam, string doug, string sauc)
{
name = nam;
dough = doug;
sauce = sauc;
}
void addTops(string tops)
{
toppings.push_back(tops);
}
void prepare()
{
cout << "Preparing " << name << endl;
cout << "Tossing dough" << endl;
cout << "Adding sauce" << endl;
cout << "Adding toppings" << endl;
list
装饰者模式
最后更新于:2022-04-01 20:29:18
## 模式定义:
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者和被装饰者有相同的超累类型。
可以用一个或多个装饰者包装一个对象。
既然装饰者和被装饰者对象有相同的超累类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
装饰者可以委托被装饰者的行为之前与或之后,加上自己的行为,以达到特定的目的。
对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458d4c2a9.jpg)
## 举例:
购买咖啡时,可以在其中加入各种调料,例如:蒸奶(Steamed Milk),豆浆(Soy),摩卡(Mocha)或覆盖奶泡。咖啡馆会根据所加入的调料收取不同的费用。
解决方法:我们以饮料为主体,然后在运行时以调料来装饰饮料。比方说顾客想要摩卡和奶泡深焙咖啡,那么,要做的是:拿一个深焙咖啡(DarkRoast)对象,以摩卡(Mocha)对象装饰它,以奶泡对象装饰它,调用cost()方法,并依赖委托将调料的价钱加上去。
## UML设计:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458dcf1e5.jpg)
## 编程实现及执行结果:
~~~
#include
#include
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() <getDescription() << " $" << pBeverage2->cost() <getDescription() << " $" << pBeverage2->cost() <
';
观察者模式
最后更新于:2022-04-01 20:29:16
## 模式定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
## 模式结构:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458ce17d6.jpg)
## 举例:
气象系统有三个部分分别是气象站(获取实际气象数据的物理装置),WeatherData对象(用来追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。WeatherData对象知道如何根物理气象站联系,以取得更新信息。WeatherData对象会随机更新三个布告板的显示:目前状况(温度,湿度,气压)、气象统计和天气预报。我们的工作是建立一个 应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计和天气预报。
## 设计UML:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458d24140.jpg)
## 代码实现及执行结果:
~~~
#include
#include
';
-
using namespace std;
//以下是观察者和主题的基类,其中DisplayElement是一个抽象类,用来//使子类实现显示功能
classObserver
{
public:
virtual ~Observer(){};
virtual void update(float temp, floathumidity, float pressure){};
};
classDisplayElement
{
public:
virtual ~DisplayElement(){};
virtual voiddisplay() = 0;
};
classSubject
{
public:
virtual ~Subject(){};
virtual voidregsiterObserver(Observer* o){} ;
virtual voidremoveObserver(Observer* o){};
virtual voidnotifyObserver(){};
};
//以下是WeatherData类,实现了注册,删除和通知观察者的功能。
classWeatherData : public Subject
{
public:
void regsiterObserver(Observer* o)
{
observers.push_back(o);
}
void removeObserver(Observer* o)
{
observers.remove(o);
}
void notifyObservers()
{
list
策略模式
最后更新于:2022-04-01 20:29:14
## 模式定义
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
## 模式结构
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458c7e6e4.jpg)
## 举例:
游泳池中有不同种类的鸭子,有绿头鸭,红头鸭,橡皮鸭,木头鸭等。不同鸭子的特征或行为不同。绿头鸭(MallardDuck)可以叫声是“quack”,会飞;橡皮鸭叫声是“queak”,不会飞;木头鸭不会叫,也不会飞。利用面向对象原理来设计来泳池中的各种鸭。要求:1.可扩展性好,当有新鸭加入时或鸭的行为有变动时,不用大量改动代码;2.复用性强。
## 设计UML图
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-30_57c5458cb307e.jpg)
其中,Duck为一个基类,MallardDuck,RedheadDuck, RubberDuck, DecoyDuck继承自Duck。
FlyBehavior, QuackBehavior为鸭子的飞行和叫声行为,在java中可用接口表示,在C++中用抽象类表示。FlyWithWings等方法用来实现鸭子的行为。
## 代码实现及执行结果:
~~~
#include
//飞行行为,用抽象类表示
classFlyBehavior{
public:
virtual ~FlyBehavior(){};
virtual void fly() =0;
};
//叫声行为,用抽象类表示
classQuackBehavior{
public:
virtual ~QuackBehavior(){};
virtual void quack()= 0;
};
//鸭子基类,有display,performFly, performQuack,swim等方法。
classDuck{
public:
Duck(FlyBehavior*p_FlyBehavior,QuackBehavior* p_QuackBehavior)
{
pFlyBehavior= p_FlyBehavior;
pQuackBehavior= p_QuackBehavior;
}
virtual ~Duck(){};
virtual voiddisplay(){};
void performFly()
{
pFlyBehavior->fly();
}
void performQuack()
{
pQuackBehavior->quack();
}
void swim()
{
std::cout<<("All ducks float, even decoys!")<< std::endl;
}
private:
FlyBehavior*pFlyBehavior;
QuackBehavior*pQuackBehavior;
};
//实现飞行行为的方法类
classFlyWithWings : public FlyBehavior{
public:
void fly(){
std::cout<< ("I'm flying!!")<>")<< std::endl;
}
};
classSqueak : public QuackBehavior{
public:
void quack(){
std::cout<< "Squeak"<performFly();
mallard->performQuack();
return 0;
}
~~~
执行结果如下:
I'm flying!!
Quack
请按任意键继续. . .
## 设计原则
可扩张性:当有新类型鸭子加入时,只要让其继承Duck类,并添加相应的行为方法类,初始化式用需要的行为方法类来初始化即可。
复用性:如会飞的鸭都可以用FlyWithWings。
设计原则的应用:
设计原则1:找出应用中可能需要变化之处,把他们独立出来,不要和哪些不需要变化的代码混在一起。(另外一种表述:将会变化的部分取出来并封装起来,好让其他部分不会受影响)。如上述例子中的FlyBehavior和QuackBehavior行为。
设计原则2:针对接口编程,而不是针对实现编程。如上述例子中的FlyBehavior和QuackBehavior,它们的实现都将实现其中的一个接口,而鸭子基类不会负责实现FlyBehavior和QuackBehavior接口。
设计原则3:多用组合,少用继承。如本例中,每一鸭子都有一个FlyBehavior和QuackBehavior。
参考
Head First设计模式
';
前言
最后更新于:2022-04-01 20:29:11
> 原文出处:[设计模式C++实现](http://blog.csdn.net/column/details/walker1.html)
作者:[walkerkalr](http://blog.csdn.net/walkerkalr)
**本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!**
# 设计模式C++实现
> 通常我们所读的设计模式书籍包括著名的Head First设计模式,大话设计模式使用Java和C#实现,用C++实现的比较少。而四人帮写的设计模式虽然用C++实现,但对于初学者读起来较难。本专栏提取Head First设计模式中的重点,并用C++实现了书中的例子。望对读者有所帮助。
';