-
Notifications
You must be signed in to change notification settings - Fork 0
/
15.iterator_pattern.h
158 lines (143 loc) · 4.34 KB
/
15.iterator_pattern.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//
// Created by Tianyi Zhang on 2/22/21.
//
#ifndef DESIGN_PATTERN_15_ITERATOR_PATTERN_H
#define DESIGN_PATTERN_15_ITERATOR_PATTERN_H
#include <memory>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
//hash function for MenuItem
struct MenuItem;
template <>
struct std::hash<MenuItem>
{
std::size_t operator()(const MenuItem& k) const;
};
struct MenuItem{
MenuItem(std::string const& name, double price): name_(name), price_(price){};
void printItem(){
std::cout<<name_<<","<<price_<<std::endl;
}
bool operator==(const MenuItem &other) const{
return (name_ == other.name_&& price_ == other.price_);
}
private:
std::string name_;
double price_;
friend class std::hash<MenuItem>;
};
std::size_t std::hash<MenuItem>::operator()(const MenuItem& k) const
{
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<string>()(k.name_)
^ (hash<double>()(k.price_) << 1)) >> 1);
}
struct MenuItemIterator{
virtual bool hasNext() = 0;
virtual void next() = 0;
virtual MenuItem getMenuItem() = 0;
};
struct BreakfastMenuIterator: public MenuItemIterator{
BreakfastMenuIterator( std::vector<MenuItem> const& menuItems) : menuItems_(menuItems){
curIterator_ = menuItems_.begin();
}
bool hasNext() override{
if(curIterator_ == menuItems_.end())
return false;
else
return true;
}
void next() override{
curIterator_ = ++curIterator_;
}
MenuItem getMenuItem() override{
return *curIterator_;
}
private:
std::vector<MenuItem>::iterator curIterator_;
std::vector<MenuItem> menuItems_;
};
struct LunchMenuIterator: public MenuItemIterator{
LunchMenuIterator( std::unordered_map<MenuItem, bool> const& menuItems) : menuItems_(menuItems){
curIterator_ = menuItems_.begin();
iterateToNextTrueItem();
}
bool hasNext() override{
iterateToNextTrueItem();
if(curIterator_ == menuItems_.end())
return false;
else
return true;
}
void next() override{
curIterator_ = ++curIterator_;
iterateToNextTrueItem();
}
MenuItem getMenuItem() override{
iterateToNextTrueItem();
return curIterator_->first;
}
private:
void iterateToNextTrueItem(){
while(curIterator_!=menuItems_.end() && curIterator_->second == false)
curIterator_ = ++curIterator_;
}
std::unordered_map<MenuItem, bool>::iterator curIterator_;
std::unordered_map<MenuItem, bool> menuItems_;
};
struct BreakfastMenu{
BreakfastMenu(){
addItem("egg",2);
addItem("hashBrown", 1);
}
void addItem(std::string const& name, double price){
menuItems_.push_back(MenuItem(name, price));
}
std::shared_ptr<MenuItemIterator> createIterator(){
return std::make_shared<BreakfastMenuIterator>(menuItems_);
}
private:
std::vector<MenuItem> menuItems_;
};
struct LunchMenu{
LunchMenu(){
addItem("rice",2, true);
addItem("bao", 1, false);
addItem("lamb", 5, true);
}
void addItem(std::string const& name, double price, bool display){
menuItems_[MenuItem(name, price)] = display;
}
std::shared_ptr<MenuItemIterator> createIterator(){
return std::make_shared<LunchMenuIterator>(menuItems_);
}
private:
std::unordered_map<MenuItem,bool> menuItems_;
};
struct Waitress{
Waitress(BreakfastMenu const& breakfastMenu, LunchMenu const& lunchMenu):breakfastMenu_(breakfastMenu), lunchMenu_(lunchMenu){};
void printMenu(){
auto breakIt = breakfastMenu_.createIterator();
std::cout<<"Print breakfast Menu"<<std::endl;
printMenu(breakIt);
auto lunchIt = lunchMenu_.createIterator();
std::cout<<"Printing lunch Menu"<<std::endl;
printMenu(lunchIt);
}
private:
//without this pattern, we need two different printMenu function as std::vector and map needs to be handled differently
void printMenu(std::shared_ptr<MenuItemIterator> mIt){
while(mIt->hasNext()){
mIt->getMenuItem().printItem();
mIt->next();
}
}
BreakfastMenu breakfastMenu_;
LunchMenu lunchMenu_;
};
#endif //DESIGN_PATTERN_15_ITERATOR_PATTERN_H