美文网首页
设计模式——组合模式

设计模式——组合模式

作者: DevilRoshan | 来源:发表于2020-11-04 00:30 被阅读0次

    什么是组合模式?

    将对象组合成树形结构以表示“部分-整体”的层次结构,用户对单个对象和组合对象的使用具有一致性。

    实现

    // 抽象公司
    type Company interface {
        Add(company Company)
        Remove(company Company)
        Display(depth int)
        LineOfDuty()
    }
    
    // 具体公司
    type ConcreteCompany struct {
        name         string
        companySlice []Company
    }
    
    func NewConcreteCompany(name string) *ConcreteCompany {
        return &ConcreteCompany{name: name}
    }
    
    func (this *ConcreteCompany) Add(company Company) {
        this.companySlice = append(this.companySlice, company)
    }
    
    func (this *ConcreteCompany) Remove(company Company) {
        for idx, comp := range this.companySlice {
            if comp == company {
                this.companySlice = append(this.companySlice[:idx], this.companySlice[idx+1:]...)
            }
        }
    }
    
    func (this *ConcreteCompany) Display(depth int) {
        for i := 0; i < depth; i++ {
            fmt.Print("-")
        }
        fmt.Println(this.name)
        for _, company := range this.companySlice {
            company.Display(depth + 1)
        }
    }
    
    func (this *ConcreteCompany) LineOfDuty() {
        for _, company := range this.companySlice {
            company.LineOfDuty()
        }
    }
    
    // 人力资源部
    type HRDepartment struct {
        name         string
        companySlice []Company
    }
    
    func NewHRDepartment(name string) *HRDepartment {
        return &HRDepartment{name: name}
    }
    
    func (this *HRDepartment) Add(company Company) {
    }
    
    func (this *HRDepartment) Remove(company Company) {
    }
    
    func (this *HRDepartment) Display(depth int) {
        for i := 0; i < depth; i++ {
            fmt.Print("-")
        }
        fmt.Println(this.name)
    }
    
    func (this *HRDepartment) LineOfDuty() {
        fmt.Println("员工招聘培训管理: ", this.name)
    }
    
    // 财务部
    type FinanceDepartment struct {
        name         string
        companySlice []Company
    }
    
    func NewFinanceDepartment(name string) *FinanceDepartment {
        return &FinanceDepartment{name: name}
    }
    
    func (this *FinanceDepartment) Add(company Company) {
    }
    
    func (this *FinanceDepartment) Remove(company Company) {
    }
    
    func (this *FinanceDepartment) Display(depth int) {
        for i := 0; i < depth; i++ {
            fmt.Print("-")
        }
        fmt.Println(this.name)
    }
    
    func (this *FinanceDepartment) LineOfDuty() {
        fmt.Println("公司财务收支管理: ", this.name)
    }
    
    
    func TestNewConcreteCompany(t *testing.T) {
        // 总公司
        root := NewConcreteCompany("东莞总公司")
        root.Add(NewFinanceDepartment("总公司财务部"))
        root.Add(NewHRDepartment("总公司人力资源部"))
        // 上海分公司
        companySH := NewConcreteCompany("上海分公司")
        companySH.Add(NewFinanceDepartment("上海公司财务部"))
        companySH.Add(NewHRDepartment("上海公司人力资源部"))
        root.Add(companySH)
        // 南京分公司
        companyNJ := NewConcreteCompany("南京分公司")
        companyNJ.Add(NewFinanceDepartment("南京公司财务部"))
        companyNJ.Add(NewHRDepartment("南京公司人力资源部"))
        root.Add(companyNJ)
        // 深圳分公司
        companySZ := NewConcreteCompany("深圳分公司")
        companySZ.Add(NewFinanceDepartment("深圳公司财务部"))
        companySZ.Add(NewHRDepartment("深圳公司人力资源部"))
        root.Add(companySZ)
        // 取消上海分公司
        root.Remove(companySH)
    
        fmt.Println("结构图")
        root.Display(1)
    
        fmt.Println("职责")
        root.LineOfDuty()
    }
    // === RUN   TestNewConcreteCompany
    // 结构图
    // -东莞总公司
    // --总公司财务部
    // --总公司人力资源部
    // --南京分公司
    // ---南京公司财务部
    // ---南京公司人力资源部
    // --深圳分公司
    // ---深圳公司财务部
    // ---深圳公司人力资源部
    // 职责
    // 公司财务收支管理:  总公司财务部
    // 员工招聘培训管理:  总公司人力资源部
    // 公司财务收支管理:  南京公司财务部
    // 员工招聘培训管理:  南京公司人力资源部
    // 公司财务收支管理:  深圳公司财务部
    // 员工招聘培训管理:  深圳公司人力资源部
    // /--- PASS: TestNewConcreteCompany (0.00s)
    // PASS
    

    优点

    • 高层模块调用简单。一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,高层模块不必关心自己处理的是单个对象还是整个组合结构;
    • 节点自由增加;

    缺点

    • 使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒转原则。

    使用场景

    • 维护和展示部分-整体关系的场景(如树形菜单、文件和文件夹管理);
    • 从一个整体中能够独立出部分模块或功能的场景。

    相关文章

      网友评论

          本文标题:设计模式——组合模式

          本文链接:https://www.haomeiwen.com/subject/pjqyvktx.html