设计模式-组合模式
2009 年 5 月 8 日
组合模式(Composite Pattern):将对象组合成树形结构表示来“部分-整体”的层次结构,使用户对单个对象和组合对象的使用具有一致性。
看上去有点抽象,其实就是一种树形结构。比如二叉树,每个非叶子节点都有2个子节点,叶子节点除了没有子节点外和父节点、根节点都是一样的。在通俗来说,比如公司的层级架构,从老板(根节点)到经理(非叶子节点)再到员工(叶子节点),他们有很多共性的东西,比如都有姓名、工号,老板和经理有添加、移除手下员工的能力,而作为员工则只能干活。
从代码实现来说,就是老板、经理、员工使用一个抽象类,而老板和经理实现某些特定的方法,这就是组合模式,十分容易理解。
package main import ( "fmt" ) type duty interface { addStaff(d duty) getStaff() []duty printUserInfo() printEmployeesInfo() } type Staff struct { number string name string position string } func (s *Staff) printUserInfo() { fmt.Printf("ID:%s,Name:%s,position:%s\n", s.number, s.name, s.position) } func (s *Staff) printEmployeesInfo() { return } func (s *Staff) addStaff(d duty) { return } func (s *Staff) getStaff() []duty { return []duty{} } type Manager struct { self Staff arr []duty } func (m *Manager) getStaff() []duty { return m.arr } func (m *Manager) addStaff(d duty) { m.arr = append(m.arr, d) } func (m *Manager) printUserInfo() { m.self.printUserInfo() } func (m *Manager) printEmployeesInfo() { for _, e := range m.arr { e.printUserInfo() for _, ee := range e.getStaff() { ee.printUserInfo() ee.printEmployeesInfo() } } } type Employees struct { self Staff } func (e *Employees) addStaff(d duty) { return } func (e *Employees) getStaff() []duty { return []duty{} } func (e *Employees) printUserInfo() { e.self.printUserInfo() } func (e *Employees) printEmployeesInfo() { return } func main() { ceo := Manager{self: Staff{name: "ceo", number: "001", position: "CEO"}} techM := Manager{self: Staff{name: "技术经理", number: "002", position: "技术经理"}} techMG1 := Manager{self: Staff{name: "技术组长1", number: "004", position: "技术组长"}} techMG2 := Manager{self: Staff{name: "技术组长2", number: "005", position: "技术组长"}} finaM := Manager{self: Staff{name: "财务经理", number: "003", position: "财务经理"}} emp1 := Employees{self: Staff{name: "开发1", number: "0041", position: "开发人员"}} emp2 := Employees{self: Staff{name: "开发2", number: "0052", position: "开发人员"}} emp3 := Employees{self: Staff{name: "财务1", number: "0031", position: "财务人员"}} ceo.addStaff(&techM) ceo.addStaff(&finaM) techM.addStaff(&techMG1) techM.addStaff(&techMG2) techMG1.addStaff(&emp1) techMG2.addStaff(&emp2) finaM.addStaff(&emp3) ceo.printUserInfo() ceo.printEmployeesInfo() }
程序输出如下:
ID:001,Name:ceo,position:CEO ID:002,Name:技术经理,position:技术经理 ID:004,Name:技术组长1,position:技术组长 ID:0041,Name:开发1,position:开发人员 ID:005,Name:技术组长2,position:技术组长 ID:0052,Name:开发2,position:开发人员 ID:003,Name:财务经理,position:财务经理 ID:0031,Name:财务1,position:财务人员
如果不使用组合模式,代码则需要建立一个 Manager
类,里面有添加、展示员工方法,再建立一个 Employees
类表示员工,这个类仅有 printUserInfo
方法。而使用组合模式,则将这2者统一为 Staff
类的子类实现相关接口即可,这也是面向抽象编程的思想。