组合模式:通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性
组合模角色构成:
首先定义一个组织的行为接口,这个接口大到总公司小到一个部门都得实现:
接口里提供两个方法,一个是打印出自己的组织结构的方法display()
另外一个是展示组织职责的方法duty()
。
// 表示组织机构的接口
type Organization interface {
display()
duty()
}
定义和实现组合对象
type CompositeOrganization struct {
orgName string
depth int
list []Organization
}
func NewCompositeOrganization(name string, depth int) *CompositeOrganization {
return &CompositeOrganization{name, depth, []Organization{}}
}
func (c *CompositeOrganization) add(org Organization) {
if c == nil {
return
}
c.list = append(c.list, org)
}
func (c *CompositeOrganization) remove(org Organization) {
if c == nil {
return
}
for i, val := range c.list {
if val == org {
c.list = append(c.list[:i], c.list[i+1:]...)
return
}
}
return
}
func (c *CompositeOrganization) display() {
if c == nil {
return
}
fmt.Println(strings.Repeat("-", c.depth * 2), " ", c.orgName)
for _, val := range c.list {
val.display()
}
}
func (c *CompositeOrganization) duty() {
if c == nil {
return
}
for _, val := range c.list {
val.duty()
}
}
组合对象用来表示有下属部门的组织,在代码里可以看到,它持有一个[]Organization
类型的列表,这里存放的是它的下属组织。组合对象的display
、duty
这两个方法的实现完全就是把工作委托给他们的下属组织来做的,这也是组合模式的特点。
两个职能部门人力资源和财务部门的类型实现。
type HRDOrg struct {
orgName string
depth int
}
func (o *HRDOrg) display() {
if o == nil {
return
}
fmt.Println(strings.Repeat("-", o.depth * 2), " ", o.orgName)
}
func (o *HRDOrg) duty() {
if o == nil {
return
}
fmt.Println(o.orgName, "员工招聘培训管理")
}
// Leaf对象--财务部门
type FinanceOrg struct {
orgName string
depth int
}
func (f *FinanceOrg) display() {
if f == nil {
return
}
fmt.Println(strings.Repeat("-", f.depth * 2), " ", f.orgName)
}
func (f *FinanceOrg) duty() {
if f == nil {
return
}
fmt.Println(f.orgName, "员工招聘培训管理")
}
只要在客户端中组合好组织架构的结构,不管有几层组织,客户端对整个组织的调用是不会改变的。
func main() {
root := NewCompositeOrganization("北京总公司", 1)
root.add(&HRDOrg{orgName: "总公司人力资源部", depth: 2})
root.add(&FinanceOrg{orgName: "总公司财务部", depth: 2})
compSh := NewCompositeOrganization("上海分公司", 2)
compSh.add(&HRDOrg{orgName: "上海分公司人力资源部", depth: 3})
compSh.add(&FinanceOrg{orgName: "上海分公司财务部", depth: 3})
root.add(compSh)
compGd := NewCompositeOrganization("广东分公司", 2)
compGd.add(&HRDOrg{orgName: "广东分公司人力资源部", depth: 3})
compGd.add(&FinanceOrg{orgName: "南京办事处财务部", depth: 3})
root.add(compGd)
fmt.Println("公司组织架构:")
root.display()
fmt.Println("各组织的职责:")
root.duty()
}
组合模式和装饰器模式在结构上很像,拥有非常相似的类结构.
组合模式:为叶子对象和组合对象提供了统一的接口,叶子对象分担组合对象所有要做的工作。工作完成后向上层调用者返回
装饰器模式:被装饰对象完成核心工作,装饰器承担修饰工作。
组合模式的优点主要有以下两点