组合模式

模式动机

组合模式统一对象和对象集,使得使用相同接口使用对象和对象集。

组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点。

Go语言实现

composite.go

  1. package composite
  2. import "fmt"
  3. type Component interface {
  4. Parent() Component
  5. SetParent(Component)
  6. Name() string
  7. SetName(string)
  8. AddChild(Component)
  9. Print(string)
  10. }
  11. const (
  12. LeafNode = iota
  13. CompositeNode
  14. )
  15. func NewComponent(kind int, name string) Component {
  16. var c Component
  17. switch kind {
  18. case LeafNode:
  19. c = NewLeaf()
  20. case CompositeNode:
  21. c = NewComposite()
  22. }
  23. c.SetName(name)
  24. return c
  25. }
  26. type component struct {
  27. parent Component
  28. name string
  29. }
  30. func (c *component) Parent() Component {
  31. return c.parent
  32. }
  33. func (c *component) SetParent(parent Component) {
  34. c.parent = parent
  35. }
  36. func (c *component) Name() string {
  37. return c.name
  38. }
  39. func (c *component) SetName(name string) {
  40. c.name = name
  41. }
  42. func (c *component) AddChild(Component) {}
  43. func (c *component) Print(string) {}
  44. type Leaf struct {
  45. component
  46. }
  47. func NewLeaf() *Leaf {
  48. return &Leaf{}
  49. }
  50. func (c *Leaf) Print(pre string) {
  51. fmt.Printf("%s-%s\n", pre, c.Name())
  52. }
  53. type Composite struct {
  54. component
  55. childs []Component
  56. }
  57. func NewComposite() *Composite {
  58. return &Composite{
  59. childs: make([]Component, 0),
  60. }
  61. }
  62. func (c *Composite) AddChild(child Component) {
  63. child.SetParent(c)
  64. c.childs = append(c.childs, child)
  65. }
  66. func (c *Composite) Print(pre string) {
  67. fmt.Printf("%s+%s\n", pre, c.Name())
  68. pre += " "
  69. for _, comp := range c.childs {
  70. comp.Print(pre)
  71. }
  72. }

composite_test.go

  1. package composite
  2. func ExampleComposite() {
  3. root := NewComponent(CompositeNode, "root")
  4. c1 := NewComponent(CompositeNode, "c1")
  5. c2 := NewComponent(CompositeNode, "c2")
  6. c3 := NewComponent(CompositeNode, "c3")
  7. l1 := NewComponent(LeafNode, "l1")
  8. l2 := NewComponent(LeafNode, "l2")
  9. l3 := NewComponent(LeafNode, "l3")
  10. root.AddChild(c1)
  11. root.AddChild(c2)
  12. c1.AddChild(c3)
  13. c1.AddChild(l1)
  14. c2.AddChild(l2)
  15. c2.AddChild(l3)
  16. root.Print("")
  17. // Output:
  18. // +root
  19. // +c1
  20. // +c3
  21. // -l1
  22. // +c2
  23. // -l2
  24. // -l3
  25. }