当前位置: 代码迷 >> 综合 >> Head First 设计模式 Design Pattern 9-10 Iterator and Composite, State
  详细解决方案

Head First 设计模式 Design Pattern 9-10 Iterator and Composite, State

热度:35   发布时间:2023-12-20 11:24:56.0

Section 9 迭代器与组合模式 Iterator and Composite

对象超集合 super collection 聚合 aggregate

>注意remove()在多线程中的状况

 


迭代器模式 提供一种方法顺序访问一个聚合对象中的各个元素, 不暴露其内部的表示.

>内部迭代器, 外部迭代器, 迭代器的数据结构可以是有序的, 无序的, 重复的.

设计原则 一个类应该只有一个引起变化的原因. (单一责任)

>类的每个责任都有改变的潜在区域. 超过一个责任, 意味着超过一个改变的区域.  避免类内的改变, 控制类的维护复杂度.

>内聚 conhesion 度量一个类或模块紧密地达到单一目的或责任. 高内聚: 类设计成只支持一组相关的功能; 低内聚: 类被设计成支持一组不相关的功能.

>策略-封装可互换的行为, 使用委托决定使用哪个; 适配器-改变一个或多个类的接口; 迭代器-提供一个方式来遍历集合, 无须暴露集合的实现; 外观-简化一群类的接口; 

组合-客户可以将对象的集合以及个别的对象一视同仁.; 观察者-当某个状态改变时, 允许一群对象被通知到.

组合模式 Composite Pattern 允许将对象组合成树形结构来表现'整体/部分'层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合.

组合模式用树形方式创建对象结构, 包含了组合和个别对象. 可以把相同的操作应用在组合和个别对象上.

>Menu是节点, MenuItem是叶节点;


>组合模式以单一责任设计原则换取透明性(transparency), 元素是组合还是叶节点对客户是透明的.

>Java for/in语句遍历: for (Object obj : collection) 递归

Summary

>要点 迭代器允许访问聚合的元素, 不需要暴露内部结构; 迭代器将遍历聚合的工作封装进一个对象中; 依赖聚合提供遍历; 迭代器提供一个公用的接口来遍历聚合项, 编码使用

聚合的项时, 可以使用多态机制; 尽量一个类只分配一个责任; 组合模式提供一个结构, 可同时包容个别和组合对象, 一视同仁; 组合结构内的任意对象称为组件, 可以是组合, 也

可以是节点; 根据需要平衡透明性和安全性来选择不同的方式设计组合模式.

Composite/Components, Iteration/Implementation, Recursion, FactoryMethod, Leaf, SingleResponseibility, HashTable, Dessert

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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//***********Iterator & Composite**********
class MenuItem;
class MenuComponent;
                                      
class IIterator
{
public:
    virtual bool hasNext()= 0;
    virtual MenuComponent* next() = 0; 
    virtual void remove() = 0;
};
                                      
class NullIterator : public IIterator
{
public:
    NullIterator() {};  
    virtual bool hasNext() { return false;}
    virtual MenuComponent* next() { return NULL;} 
    virtual void remove() {cout << "Unsupported" << endl;}
};
                                      
class MenuComponent
{
public:
    MenuComponent() {};
    virtual void add(MenuComponent* menuComponent) {cout << "Unsupported" << endl;}
    virtual void remove(MenuComponent* menuComponent) {cout << "Unsupported" << endl;}
    virtual MenuComponent* getChild(int i) {cout << "Unsupported" << endl;}
    virtual string getName() {cout << "Unsupported" << endl;}
    virtual double getPrice() {cout << "Unsupported" << endl;}
    virtual void print() {cout << "Unsupported" << endl;}
    virtual IIterator* createIterator() = 0;
};
                                      
class MenuItem : public MenuComponent
{
public:
    MenuItem(string name, double price) : msName(name), mdPrice(price) {}
    string getName() { return msName;}
    double getPrice() { return mdPrice;}
    void print();
    virtual IIterator* createIterator() { return new NullIterator();}
private:
    string msName;
    double mdPrice;
};
                                      
typedef vector<MenuComponent*> MENUCOMPONENTVEC;
class Menu : public MenuComponent
{
public:
    Menu(string name) : msName(name) {};
    virtual IIterator* createIterator();
    void add(MenuComponent* menuCom) {menuComVec.push_back(menuCom);}
    void remove(MenuComponent* menuCom);
    MenuComponent* getChild(int i) { menuComVec.at(i); }
    virtual string getName() { return msName;}
    void print();      
private:
    MENUCOMPONENTVEC menuComVec;
    string msName;
};
                                      
typedef vector<MenuItem*> MENUITEMVEC;
class PancakeHouseMenu : public Menu
{
public:
    PancakeHouseMenu();
    MENUITEMVEC getMenuItems(){ return menuIVec; }
    virtual IIterator* createIterator();
private:
    void addItem(string name, double price);
    MENUITEMVEC menuIVec;
};
                                      
class DinerMenu : public Menu
{
public:
    DinerMenu();
    ~DinerMenu();
    MenuItem** getMenuItems() { return menuItems; }
    int getSize() { return miNumOfItems;}
    virtual IIterator* createIterator();
private:
    void addItem(string name, double price);
    MenuItem** menuItems;
    int miNumOfItems;
};
                                      
typedef map<string, MenuItem*> MENUMAP;
class CafeMenu : public Menu
{
public:
    CafeMenu();
    MENUITEMVEC getMenuItems() { return menuVec;}
    virtual IIterator* createIterator();
private:
    void addItem(string name, double price);
    MENUMAP menuMap;
    MENUITEMVEC menuVec;
};
                                      
class DinerMenuIterator : public IIterator
{
public:
    DinerMenuIterator(MenuItem** items, int size) : miPosition(0)
    {
        menuItems = items;
        miSize = size;
    }
    virtual bool hasNext();
    virtual MenuItem* next();
    virtual void remove();
private:
    MenuItem** menuItems;
    int miPosition;
    int miSize;
};
                                      
class PancakeHouseMenuIterator : public IIterator
{
public:
    PancakeHouseMenuIterator(MENUITEMVEC vec)
    {
        menuIVec = vec;
        mIter = menuIVec.begin();
    }
    virtual bool hasNext();
    virtual MenuItem* next();
    virtual void remove();
private:
    MENUITEMVEC menuIVec;
    MENUITEMVEC::iterator mIter;
};
                                      
class CafeMenuIterator : public IIterator
{
public:
    CafeMenuIterator(MENUITEMVEC vec)
    {
        menuVec = vec;
        mIter = menuVec.begin();
    }
    virtual bool hasNext();
    virtual MenuItem* next();
    virtual void remove();
private:
    MENUITEMVEC menuVec;
    MENUITEMVEC::iterator mIter;
};
                                      
typedef vector<Menu*> MENUSVEC;
class Waitness
{
public:
    Waitness();
    void setMenuComponent(MenuComponent* menuCom)
    {menuComponent = menuCom;}
    void setPCMenu(Menu* menu);
    void setDinerMenu(Menu* menu);
    void setCafeMenu(Menu* menu);
    void addMenus(Menu* menu);
    void printMenu();
    void printMenu(IIterator* iter);
    void printMenus();
    void printMenuComponent();
    void removeMenuComponent();
private:
    Menu* mpPancakeMenu;
    Menu* mpDinerMenu;
    Menu* mpCafeMenu;
    MENUSVEC menusVec;
    MenuComponent* menuComponent;
};
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
//***********Iterator & Composite**********
void MenuItem::print()
{
    cout<<"------MenuItem------"<< endl;
    cout << "Name:"<<getName() << endl;
    cout << "Price:"<<getPrice() << endl;
}
                                      
IIterator* Menu::createIterator()
{
    return new NullIterator();
}
                                      
void Menu::remove(MenuComponent* menuCom)
{
    MENUCOMPONENTVEC::iterator iter = menuComVec.begin();
    for (; iter != menuComVec.end(); iter++)
    {
        MenuComponent* menuComToCompare = *iter;
        if (menuComToCompare == menuCom)
        {
            iter = menuComVec.erase(iter);
            return;
        }
    }
}
                                      
void Menu::print()
{
    cout<<"------Menu------"<< endl;
    cout << "Name:"<<getName() << endl;
    MENUCOMPONENTVEC::iterator iter = menuComVec.begin();
    for (; iter != menuComVec.end(); iter++)
    {
        MenuComponent* menuCom = *iter;
        menuCom->print();
    }    
}
                                      
const int MAX_ITEMS = 6;
PancakeHouseMenu::PancakeHouseMenu()
: Menu("PancakeHouse")
{
    addItem("Regular Pancake Breakfast", 15.90);
    addItem("BlueBerry Pancake", 18.90);
}
                                      
void PancakeHouseMenu::addItem(string name, double price)
{
    MenuItem *item = new MenuItem(name, price);
    menuIVec.push_back(item);
}
                                      
IIterator*  PancakeHouseMenu::createIterator()
{
    return new PancakeHouseMenuIterator(menuIVec);
}
                                      
DinerMenu::DinerMenu()
: Menu("Diner"),
  miNumOfItems(0)
{
    //*menuItems = new MenuItem[MAX_ITEMS; //wrong: runtime creating, terminate error, only for assign the value, not new
    menuItems = new MenuItem*[MAX_ITEMS];
    addItem("Soup of the day", 5.00);
    addItem("Hotdog", 8.00);
}
                                      
DinerMenu::~DinerMenu()
{
    delete[] menuItems;
}
                                      
void DinerMenu::addItem(string name, double price)
{
    MenuItem* item = new MenuItem(name, price);
    if (MAX_ITEMS > miNumOfItems)
    {
        menuItems[miNumOfItems] = item;
        miNumOfItems++;
    }
    else
        cout << "Menu is full, can't add more." << endl;
}
                                      
IIterator* DinerMenu::createIterator()
{
    return new DinerMenuIterator(menuItems, miNumOfItems);
}
                                      
CafeMenu::CafeMenu()
: Menu("Cafe")
{
    addItem("Soup of the day", 3.59);
    addItem("Cappuccino ", 1.99);
}
                                      
void CafeMenu::addItem(string name, double price)
{
    MenuItem* item = new MenuItem(name, price);
    menuMap.insert(pair<string,MenuItem*>(name,item));
    menuVec.push_back(item);
}
                                      
IIterator* CafeMenu::createIterator()
{
    return new CafeMenuIterator(menuVec);
}
                                      
bool DinerMenuIterator::hasNext()
{
    if(miPosition >= miSize ||
      menuItems[miPosition] == NULL)
        return false;
    else
        return true;           
}
                                      
MenuItem* DinerMenuIterator::next()
{
    MenuItem* item = menuItems[miPosition];
    miPosition++;
    return item;
}
                                      
void DinerMenuIterator::remove()
{
    if(miPosition <= 0)
    {
        cout << "Can't remove the item" << endl;
        return;
    }
    if(menuItems[miPosition - 1] != NULL)
    {
        for(int i = miPosition - 1 ; i < miSize - 1; i++)
        {
            menuItems[miPosition] = menuItems[miPosition + 1];
        }
        menuItems[miSize - 1] = NULL;
        miSize--;
    }
}
                                      
bool PancakeHouseMenuIterator::hasNext()
{
    if(mIter == menuIVec.end())
        return false;
    else
        return true;        
}
                                      
MenuItem* PancakeHouseMenuIterator::next()
{
    MenuItem* item = *mIter;
    mIter++;
    return item;
}
                                      
void PancakeHouseMenuIterator::remove()
{
    if(mIter == menuIVec.end())
    {
        cout << "Can't remove the item" << endl;
        return;
    }
    if (NULL != *mIter)
        mIter = menuIVec.erase(mIter);
}
                                      
bool CafeMenuIterator::hasNext()
{
    if(mIter == menuVec.end())
        return false;
    else
        return true
}
                                      
MenuItem* CafeMenuIterator::next()
{
    MenuItem* item = *mIter;
    mIter++;
    return item;
}
                                      
void CafeMenuIterator::remove()
{
    if (mIter == menuVec.end())
    {
        cout << "Can't remove the item" << endl;
        return;
    }
    if (NULL != *mIter)
       mIter = menuVec.erase(mIter);
}
                                      
void Waitness::printMenu()
{
    if (mpPancakeMenu != NULL)
    {
        MENUITEMVEC menuVec = dynamic_cast<PancakeHouseMenu*>(mpPancakeMenu)->getMenuItems();
        MENUITEMVEC::iterator menuIter = menuVec.begin();
        cout << "----MenuItem for PancakeHouse----" << endl;
        for (; menuIter != menuVec.end(); menuIter++)
        {
            MenuItem *item = *menuIter;
            cout << "name:" << item->getName();
            cout << " price:" << item->getPrice() << endl;
        }
        IIterator* iterPcake = mpPancakeMenu->createIterator();
        cout << "----MenuItem Iterator for PancakeHouse----" << endl;
        printMenu(iterPcake);  
    }
    if (mpPancakeMenu != NULL)
    {
        DinerMenu* dinerMenu = dynamic_cast<DinerMenu*>(mpDinerMenu);
        MenuItem** menuItems = dinerMenu->getMenuItems();
        cout << "----MenuItem  for Diner:----" << endl;
        for (int i = 0; i < dinerMenu->getSize(); i++)
        {
            MenuItem* item = menuItems[i];
            cout << "name:" << item->getName();
            cout << " price:" << item->getPrice() << endl;
        }
        IIterator* iterDiner = mpDinerMenu->createIterator();
        cout << "----MenuItem Iterator for Diner:----" << endl;
        printMenu(iterDiner);
    }
    if (mpCafeMenu != NULL)
    {
        MENUITEMVEC menuVec = dynamic_cast<CafeMenu*>(mpCafeMenu)->getMenuItems();
        MENUITEMVEC::iterator menuIter = menuVec.begin();
        cout << "----MenuItem for Cafe----" << endl;
        for (; menuIter != menuVec.end(); menuIter++)
        {
            MenuItem *item = *menuIter;
            cout << "name:" << item->getName();
            cout << " price:" << item->getPrice() << endl;
        }
        IIterator* iterCafe = mpCafeMenu->createIterator();
        cout << "----MenuItem Iterator for Cafe----" << endl;
        printMenu(iterCafe);  
    }
}
                                      
Waitness::Waitness()
: mpPancakeMenu(NULL), mpDinerMenu(NULL), mpCafeMenu(NULL)
{
}
                                      
void Waitness::setPCMenu(Menu* menu)
{
    mpPancakeMenu = menu;
}
                                      
void Waitness::setDinerMenu(Menu* menu)
{
    mpDinerMenu = menu;
}
                                      
void Waitness::setCafeMenu(Menu* menu)
{
    mpCafeMenu = menu;
}
                                      
void Waitness::printMenu(IIterator* iter)
{
    while(iter->hasNext())
    {
  相关解决方案