/***********************************
baseobject.h
***********************************/
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "CIterator.h"
#define MAX_ARRAY_SIZE 100
using namespace std;
//前置定义
class CIteratorInterface;
class CElectricIterator;
//////////////////////////////////////////
//在C++对象不像在Java中一样,有统一的基类Ojbect,
//所以,我们在这里为所有要出售的对象设定一个对象的基类
class CBaseObjectMenuItem
{
private:
string m_Name;
float m_Price;
public:
CBaseObjectMenuItem(string name, float price) : m_Name(name), m_Price(price){}
virtual float getPrice() {
return m_Price;
}
virtual string getName(){
return m_Name;
}
void showInformation(){
cout<<"Name : "<<m_Name<<"\t\t\t";
cout<<"Price : "<<m_Price<<endl;
}
};
////////////////////////////////////////////
//我这里先给出一个菜单类的接口,
//这里简单处理菜单项,假设菜单项总是由一个名字和一个价格所决定的
class CSaleMenu
{
public:
virtual void addMenuItem(string Name, float Price) = 0;
virtual CIteratorInterface* createIterator() = 0;
};
/////////////////////////////////////////
//电器菜单类,用数组实现
//其中有一个方法可以用来创建一个迭代器
class CElectricMenu : public CSaleMenu
{
private:
unsigned long m_totalItems;
//我这里也用指针的原因是为了防止对象切片(slicing)
//因为现在这里还是非常简单的情况就是,菜单对像还只是一个基类的直接对象
//如果这个对象是一个菜单项基类的派生类的对象时,切记:千万不要以数组的多态方式来处理
//这样会导致切片问题,可详见more efficient C++的相关章节
CBaseObjectMenuItem* m_ItemPointers[MAX_ARRAY_SIZE];
public:
CElectricMenu() : m_totalItems(0){}
void addMenuItem(string Name, float Price){
m_ItemPointers[m_totalItems++] = new CBaseObjectMenuItem(Name, Price);
}
inline unsigned long getTotalMenuItems(){
return m_totalItems;
}
CBaseObjectMenuItem** getMenu(){
return m_ItemPointers;
}
CIteratorInterface* createIterator();
~CElectricMenu(){
for(unsigned long i = 0; i < m_totalItems; i++)
delete m_ItemPointers[i];
}
};
/////////////////////////////////////////
//食品菜单菜,用vector实现
class CFoodMenu : public CSaleMenu
{
private:
//我这里也用指针的原因是为了防止对象切片(slicing)
//因为现在这里还是非常简单的情况就是,菜单对像还只是一个基类的直接对象
//如果这个对象是一个菜单项基类的派生类的对象时,切记:千万不要以数组的多态方式来处理
//这样会导致切片问题,可详见more efficient C++的相关章节
vector<CBaseObjectMenuItem*> m_ItemPointer;
public:
void addMenuItem(string Name, float Price){
m_ItemPointer.push_back(new CBaseObjectMenuItem(Name, Price));
}
vector<CBaseObjectMenuItem*>& getMenu(){
return m_ItemPointer;
}
CIteratorInterface* createIterator();
~CFoodMenu(){
for(int i = 0; i < static_cast<int>(m_ItemPointer.size()); i++){
delete m_ItemPointer[i];
}
m_ItemPointer.clear();
}
};
/***********************************************
CIterator.h
***********************************************/
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "baseobject.h"
using namespace std;
class CBaseObjectMenuItem;
//////////////////////////////////////////
//迭代器的接口,这是每个迭代器都要实现的.
class CIteratorInterface
{
public:
virtual bool hasNext() = 0;
virtual CBaseObjectMenuItem* next() = 0;
virtual ~CIteratorInterface() {}
};
/////////////////////////////////////////
//这是一个用于数组接口的迭代器,我们实现了电器数组的迭代
//用数据实现
class CElectricIterator : public CIteratorInterface
{
private:
unsigned long m_totalItems;
CBaseObjectMenuItem** m_MenuItem;
unsigned long m_currentIt;
public:
CElectricIterator(CBaseObjectMenuItem** inMenu, unsigned long inTI);
bool hasNext();
CBaseObjectMenuItem* next();
};
/////////////////////////////////////////
//这是一个用于vector接口的迭代器,我们实现了食物vector的迭代
//用vector实现
class CFoodIterator : public CIteratorInterface
{
private:
vector<CBaseObjectMenuItem*>& m_MenuItem;
unsigned long m_currentIt;
public:
CFoodIterator(vector<CBaseObjectMenuItem*>& inItemList);
bool hasNext();
CBaseObjectMenuItem* next();
};
/******************************************
CMenuShower.h
*******************************************/
#pragma once
#include <iostream>
#include "baseobject.h"
#include "CIterator.h"
//////////////////////////////////////////////
//是时候来做一个显然菜单的类的
//这个类是与具体菜单元素存放方式无关的(已经解耦了)
//当要具体类时,就创建一个iterator,切记,用完后要删除
class CMenuShower
{
private:
CSaleMenu* m_Menu1; //电子产品类的menu
CSaleMenu* m_Menu2; //食品类的menu
//可以像下面这样来管理所有菜单项
//vector<CSaleMenu*> m_Menus;
public:
CMenuShower(CSaleMenu* inElecMenu, CSaleMenu* inFoodMenu) :
m_Menu1(inElecMenu), m_Menu2(inFoodMenu)
{
}
private:
static void PrintSingleIterator(CIteratorInterface* it){
if(!it)
return;
while(it->hasNext()){
CBaseObjectMenuItem* tmp = it->next();
tmp->showInformation();
}
}
public:
//哈哈。这下总算是成功与菜单实现解耦了。
//如果没有解耦的话,我们还需要知道不同人实现的放在数据的方法,然后分别处理。
//在使用了迭代器模式后,我们就需要知道迭代器模式的接品即可。
void PrintAllMenuItems(){
//电器类商品, “电器类菜单说: 你打印吧,不要管我是怎么实现的”
cout<<"[电器类商品]"<<endl;
PrintSingleMenu(m_Menu1);
//食物类商品 “食物类菜单说: 你打印吧,你也不要管我是怎么实现的”
cout<<"[食物类商品]"<<endl;
PrintSingleMenu(m_Menu2);
}
public:
static void PrintSingleMenu(CSaleMenu* menu)
{
if(!menu)
return;
CIteratorInterface* it = menu->createIterator();
PrintSingleIterator(it);
delete it;
}
};
/*****************************************
baseobject.cpp
******************************************/
#include "baseobject.h"
#include "CIterator.h"
CIteratorInterface* CElectricMenu::createIterator()
{
//注意这里new了一个iterator
//在调用的地方,调用完了之后,一定要把这块内存释放掉。
return static_cast<CIteratorInterface*>(
new CElectricIterator(m_ItemPointers, m_totalItems));
}
CIteratorInterface* CFoodMenu::createIterator()
{
//注意这里new了一个iterator
//在调用的地方,调用完了之后,一定要把这块内存释放掉。
return static_cast<CIteratorInterface*>(
new CFoodIterator(m_ItemPointer));
}
/******************************************
Citerator.cpp
******************************************/
#include "CIterator.h"
#include "baseobject.h"
/////////////////////////////////////////
//这是一个用于数组接口的迭代器,我们实现了电器数组的迭代
//用数据实现
//实现部分
CElectricIterator::CElectricIterator(CBaseObjectMenuItem** inMenu, unsigned long inTI)
: m_MenuItem(inMenu), m_totalItems(inTI), m_currentIt(0){
}
bool CElectricIterator::hasNext()
{
return m_currentIt < m_totalItems ? true : false;
}
CBaseObjectMenuItem* CElectricIterator::next(){
if(m_currentIt < m_totalItems)
return m_MenuItem[m_currentIt++];
return NULL;
}
/////////////////////////////////////////
//这是一个用于vector接口的迭代器,我们实现了食物vector的迭代
//用vector实现
//实现部分
CFoodIterator::CFoodIterator(vector<CBaseObjectMenuItem*>& inItemList)
: m_MenuItem(inItemList), m_currentIt(0){
}
bool CFoodIterator::hasNext()
{
return m_currentIt < m_MenuItem.size() ? true : false;
}
CBaseObjectMenuItem* CFoodIterator::next(){
if(m_currentIt < m_MenuItem.size())
return m_MenuItem[m_currentIt++];
return NULL;
}
/***************************************************
testiteratorPattern.cpp
***************************************************/
/*
设计模式: 迭代器模式
提供一种方法顺序访问一个聚合对象的各个元素
首先,迭代器这个方法根本不管聚合究竟是由数组还是由Array或者Vector来保存的.
其次,迭代器模式把在元素之间遍历的责任交给迭代器,而不是某种特殊的聚合对象.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
这个程序运用迭代器模式来遍历一些菜单项
在程序里有两个菜单项,
一个是电子产品的菜单项 用数据实现
一个是食品的菜单项 用vector实现
现在有一个终端机,并不知道两个菜单项的内在数据的具体存储和实现方式,但需要给客户显现数据的内容.
所以,我在这里使用了迭代器模式,把迭代过程进行封装.
CIterator为迭代器的基类
在这个迭代器模式的例子中Menu子类的createIterator()是这个模式的精髓。
这个成员返回一个所有封装的迭代器的基类接口.所以使用者就不必要去关心返回的
迭代器的内部数据存储方式
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
by 何戬, hejian@cad.zju.edu.cn
*/
#include <iostream>
#include "CMenuShower.h"
using namespace std;
int main()
{
CElectricMenu* elecMenu = new CElectricMenu();
elecMenu->addMenuItem("诺基亚E71", 2300.0f);
elecMenu->addMenuItem("诺基亚N29", 2120.0f);
CFoodMenu* foodMenu = new CFoodMenu;
foodMenu->addMenuItem("KFC全家套餐", 66.0f);
foodMenu->addMenuItem("原味吮指鸡块", 7.5f);
CMenuShower* ms = new CMenuShower(elecMenu, foodMenu);
ms->PrintAllMenuItems();
delete foodMenu;
delete elecMenu;
return 0;
}