组合模式
lzh2nix opened this issue · comments
在iterator模式中解决了不同类型的collection的遍历方式,如果Diner菜单中如果还有一个子菜单(Dessert Menu)的时候,iterator就不能很好的处理了。这里打印Dessert Menu的时候又要费一番周折。
而组合模式就是解决这种复合对象的访问模式,让他们看起来和单一对象一样。
下面是Composite模式的定义
The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly
这种结构类似一个树形结构,如果是一个叶子节点就直接打印,对子树调用子树的print即可。
代码实现上也相对比较简单, 在MenuItem上新增一个Print方法。
func (m *MenuItem) Print() {
fmt.Println(m.Name + ", " + m.Desc + ", " + fmt.Sprintf("%f", m.Price))
}
然后在Menu上新增一个SubMenu,然后在print的时候时将Items和SubMenu一起打印即可。
type Menu struct {
Items list.List
SubMenu []*Menu
Name string
}
func (p *Menu) AddSubMenu(sub *Menu) {
p.SubMenu = append(p.SubMenu, sub)
}
func (p *Menu) Print() {
fmt.Println("------------------------------", p.Name, "---------------------------------")
for i := p.Items.Front(); i != nil; i = i.Next() {
i.Value.(*MenuItem).Print()
}
for i := range p.SubMenu {
p.SubMenu[i].Print()
}
}
然后在client侧直接调用复合类型的Print。
func main() {
breakFast := NewMenu("pancakeHouseMenu")
breakFast.Add("K&B's Pancake Breakfast", "Pancakes with scrambled eggs and toast", true, 2.99)
breakFast.Add("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99)
breakFast.Add("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29)
breakFast.Add("Hotdog", "A hot dog, with sauerkraut, relish, onions, topped with cheese", false, 3.05)
lunch := NewMenu("dinerMenu")
lunch.Add("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99)
lunch.Add("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99)
lunch.Add("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29)
lunch.Add("Hotdog", "A hot dog, with sauerkraut, relish, onions, topped with cheese", false, 3.05)
dessert := NewMenu("dessertMenu")
dessert.Add("Apple Pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59)
lunch.AddSubMenu(dessert)
breakFast.Print()
lunch.Print()
}