迭代器模式与组合模式
- 迭代器模式:提供一种方法顺序访问一个聚会对象中的各个元素,而不是暴露其内部的表示
- 迭代器模式用来封装变化,迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
- 迭代器模式体现的设计原则:单一责任:一个类应该只有一个引起变化的原因(类中管理数组是一个功能 遍历数组是另外一个功能两者分开)
- 组合模式:允许你将对象组合成树形结构来表现整体/部分层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。
- 迭代器允许访问聚合的元素,而不需要暴露它的内部结构。
- 迭代器将遍历聚合的工作封装进一个对象中。
- 组合模式提供一个结构,可同时包容个别对象和组合对象。
例子
![在这里插入图片描述](https://img-blog.csdnimg.cn/db2538cb95e14762b145733e376cb2fc.png)
迭代器模式示例
class Menus{
public:
virtual void* createIterator()=0;
};
class MenuItem{
private:
string name;
string description;
bool vegetarian;
double price;
public:
MenuItem(){}
MenuItem(string m_name,string m_description,bool m_vegetarian,double m_price):
name(m_name),description(m_description),vegetarian(m_vegetarian),price(m_price){}
string getName(){
return name;
}
string getDescription(){
return description;
}
double getPrice(){
return price;
}
bool isVegetarian(){
return vegetarian;
}
};
class m_iterator{
public:
virtual bool hasNext()=0;
virtual MenuItem* next()=0;
};
class DinerMenuIterator:public m_iterator{
public:
DinerMenuIterator(MenuItem** m_menuItems,int m_size):menuItems(m_menuItems),length(m_size){
}
~DinerMenuIterator(){
if(menuItems){
delete menuItems;
menuItems=nullptr;
}
}
virtual bool hasNext(){
if(length==0||position>=length){
return false;
}
return true;
}
virtual MenuItem* next(){
if(position<length)
return menuItems[position++];
}
private:
int length=0;
int position=0;
MenuItem** menuItems;
};
class PancakeMenuIterator:public m_iterator{
public:
PancakeMenuIterator(list<MenuItem>& m_menuItems):menuItems(m_menuItems){
start=menuItems.begin();
}
virtual bool hasNext(){
if(start==menuItems.end()){
return false;
}
return true;
}
virtual MenuItem* next(){
if(start!=menuItems.end()){
MenuItem* temp = &(*start);
++start;
return temp;
}
}
private:
list<MenuItem> menuItems;
list<MenuItem>::iterator start;
};
class DinerMenu:public Menus{
private:
static int MAX_ITEMS;
int numberOfItems =-1;
MenuItem** menuIems=nullptr;
public:
DinerMenu(){
menuIems = new MenuItem*[MAX_ITEMS];
addItem("Vegetarian BLT","Bacon with lettuce",true,2.99);
addItem("Soup of the day","Soup of the day , with a side of potato salad",false,3.99);
}
void addItem(string name,string description,bool vegetarian,double price){
if(numberOfItems<MAX_ITEMS){
menuIems[++numberOfItems]=new MenuItem(name,description,vegetarian,price);
}
}
int getSize(){
return numberOfItems;
}
MenuItem** getMenuItems(){
return menuIems;
}
~DinerMenu(){
if(menuIems){
delete [] menuIems;
menuIems=nullptr;
}
}
virtual void* createIterator(){
return new DinerMenuIterator(menuIems,numberOfItems+1);
}
};
int DinerMenu::MAX_ITEMS = 6;
class PancakeHouseMenu:public Menus{
private:
list<MenuItem> menuItems;
public:
PancakeHouseMenu(){
addItem("Pancake Breakfast","Pancakes with scrambled eggs",true,4.99);
addItem("Regular Breakfast","Pancakes made with fresh blueberries",true,5.99);
}
void addItem(string name,string description,bool vegetarian,double price){
menuItems.push_back(MenuItem(name,description,vegetarian,price));
}
list<MenuItem> getMenuItems(){
return menuItems;
}
virtual void* createIterator(){
return new PancakeMenuIterator(menuItems);
}
};
int main(){
vector<Menus*> menus; //总的菜单容器
DinerMenu* dinnermenu = new DinerMenu;
menus.push_back(dinnermenu); //加入菜单
PancakeHouseMenu* pancakemenu = new PancakeHouseMenu;
menus.push_back(pancakemenu);
for(int i=0;i<menus.size();++i){ //遍历每个菜单的菜
m_iterator* pointer=(m_iterator*)menus[i]->createIterator();
while(pointer->hasNext()){
MenuItem* menuitem = pointer->next();
cout<<menuitem->getName()<<" "<<menuitem->getPrice()<<endl;
}
cout<<endl<<endl;
}
system("pause");
return 0;
}
例子
![在这里插入图片描述](https://img-blog.csdnimg.cn/3d9a7374ebd547b08e9227b6ef89039b.png)
组合模式示例
class MenuComponent{
public:
virtual ~MenuComponent(){};
virtual void add(MenuComponent* menuComponent)=0;
virtual void remove(MenuComponent* menuComponent)=0;
virtual void* getChild(int i)=0;
virtual string getName()=0;
virtual string getDescription()=0;
virtual double getPrice()=0;
virtual bool isVegetarian()=0;
virtual void print()=0;
};
class MenuItem:public MenuComponent{
private:
string name;
string description;
double price;
bool vegetarian;
public:
MenuItem(string m_name,string m_description,double m_price,bool m_vegetarian)
:name(m_name),description(m_description),price(m_price),vegetarian(m_vegetarian){}
virtual void add(MenuComponent* menuComponent){return;};
virtual void remove(MenuComponent* menuComponent){return;};
virtual void* getChild(int i){return nullptr;};
virtual string getName(){
return name;
};
virtual string getDescription(){
return description;
};
virtual double getPrice(){
return price;
}
virtual bool isVegetarian(){
return vegetarian;
}
virtual void print(){
cout<<" "<<getName();
if(isVegetarian()){
cout<<"(v) ";
}
cout<<" ,"<<getPrice();
cout<<" --"<<getDescription()<<endl;
}
};
class Menu:public MenuComponent{
private:
vector<MenuComponent*> menuComponents;
string name;
string description;
public:
Menu(string m_name,string m_description)
:name(m_name),description(m_description){};
virtual void add(MenuComponent* menuComponent){
if(menuComponent){
menuComponents.push_back(menuComponent);
}
};
virtual void remove(MenuComponent* menuComponent){
for(int i=0;i<menuComponents.size();++i){
if(menuComponents[i]==menuComponent){
menuComponents.erase(menuComponents.begin()+i);
break;
}
}
};
virtual void* getChild(int i){
if(i<menuComponents.size()){
return menuComponents[i];
}
};
virtual string getName(){
return name;
};
virtual string getDescription(){
return description;
};
virtual double getPrice(){
return 0;
};
virtual bool isVegetarian(){
return false;
};
virtual void print(){
cout<<"\n"<<getName();
cout<<","<<getDescription()<<endl;
cout<<"--------------"<<endl;
for(int i=0;i<menuComponents.size();++i){
menuComponents[i]->print();
}
};
};
int main(){
MenuComponent* pancakeHouseMenu=new Menu("PANCAKE HOUSE MENU","Breakfast");
MenuComponent* dinerMenu=new Menu("DINER","Lunch");
MenuComponent* cafeMenu=new Menu("Cafe Menu","Dinner");
MenuComponent* dessertMenu=new Menu("Dessert Menu","Dessert of course!");
MenuComponent* allMenus = new Menu("ALL MENUS","ALL menus combined");
allMenus->add(pancakeHouseMenu);
allMenus->add(dinerMenu);
allMenus->add(cafeMenu);
dinerMenu->add(new MenuItem("Pasta","Spaghetti with Marinara Sauce",2.99,true));
dinerMenu->add(dessertMenu);
dessertMenu->add(new MenuItem("Apple Pie","Apple pie with a flakey crust",1.99,true));
allMenus->print();
system("pause");
return 0;
}