lzh2nix / articles

用 issue 来管理个人博客

Home Page:https://github.com/lzh2nix/articles

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

组合模式

lzh2nix opened this issue · comments

commented

在iterator模式中解决了不同类型的collection的遍历方式,如果Diner菜单中如果还有一个子菜单(Dessert Menu)的时候,iterator就不能很好的处理了。这里打印Dessert Menu的时候又要费一番周折。
2021-09-18_20-29
而组合模式就是解决这种复合对象的访问模式,让他们看起来和单一对象一样。

下面是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即可。
2021-09-18_21-52

代码实现上也相对比较简单, 在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()
}