设计模式 - 组合模式
意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项:定义时为具体类。
package main import "fmt" type Employee struct { Name string Dept string Salary int Subordinates []*Employee } func NewEmployee(name, dept string, salary int) *Employee { return &Employee{ Name: name, Dept: dept, Salary: salary, Subordinates: []*Employee{}, } } func (e *Employee) Add(employee *Employee) { e.Subordinates = append(e.Subordinates, employee) } func (e *Employee) Remove(employee *Employee) { for i, item := range e.Subordinates { if item.Name == employee.Name { e.Subordinates[i] = e.Subordinates[len(e.Subordinates)-1] e.Subordinates = e.Subordinates[:len(e.Subordinates)-1] return } } } func (e *Employee) GetSubordinates() []*Employee { return e.Subordinates } func (e *Employee) ToString() string { return fmt.Sprintf("Employee: Name: %s, Dept: %s, Salary: %d", e.Name, e.Dept, e.Salary) } func main() { ceo := NewEmployee("John", "CEO", 23333) headSales := NewEmployee("Robert", "HeadSales", 2333) headMarket := NewEmployee("Mike", "HeadMarket", 2333) clerk1 := NewEmployee("Laura", "marketing", 233) clerk2 := NewEmployee("Bob", "marketing", 233) sales1 := NewEmployee("Richard", "sales", 233) sales2 := NewEmployee("Rob", "sales", 233) ceo.Add(headSales) ceo.Add(headMarket) headMarket.Add(clerk1) headMarket.Add(clerk2) headSales.Add(sales1) headSales.Add(sales2) queue := []*Employee{ceo} for len(queue) != 0 { size := len(queue) for i := 0; i < size; i++ { employee := queue[i] fmt.Println(employee.ToString()) queue = append(queue, employee.Subordinates...) } queue = queue[size:] } }