设计模式-组合模式

组合模式(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 类的子类实现相关接口即可,这也是面向抽象编程的思想。