职责链模式

10.1 模式动机

职责链模式用于分离不同职责,并且动态组合相关职责。

Golang实现职责链模式时候,因为没有继承的支持,使用链对象包涵职责的方式,即:

  • 链对象包含当前职责对象以及下一个职责链。
  • 职责对象提供接口表示是否能处理对应请求。
  • 职责对象提供处理函数处理相关职责。

同时可在职责链类中实现职责接口相关函数,使职责链对象可以当做一般职责对象是用。

10.2 Go语言实现

chain.go

  1. package chain
  2. import "fmt"
  3. type Manager interface {
  4. HaveRight(money int) bool
  5. HandleFeeRequest(name string, money int) bool
  6. }
  7. type RequestChain struct {
  8. Manager
  9. successor *RequestChain
  10. }
  11. func (r *RequestChain) SetSuccessor(m *RequestChain) {
  12. r.successor = m
  13. }
  14. func (r *RequestChain) HandleFeeRequest(name string, money int) bool {
  15. if r.Manager.HaveRight(money) {
  16. return r.Manager.HandleFeeRequest(name, money)
  17. }
  18. if r.successor != nil {
  19. return r.successor.HandleFeeRequest(name, money)
  20. }
  21. return false
  22. }
  23. func (r *RequestChain) HaveRight(money int) bool {
  24. return true
  25. }
  26. type ProjectManager struct{}
  27. func NewProjectManagerChain() *RequestChain {
  28. return &RequestChain{
  29. Manager: &ProjectManager{},
  30. }
  31. }
  32. func (*ProjectManager) HaveRight(money int) bool {
  33. return money < 500
  34. }
  35. func (*ProjectManager) HandleFeeRequest(name string, money int) bool {
  36. if name == "bob" {
  37. fmt.Printf("Project manager permit %s %d fee request\n", name, money)
  38. return true
  39. }
  40. fmt.Printf("Project manager don't permit %s %d fee request\n", name, money)
  41. return false
  42. }
  43. type DepManager struct{}
  44. func NewDepManagerChain() *RequestChain {
  45. return &RequestChain{
  46. Manager: &DepManager{},
  47. }
  48. }
  49. func (*DepManager) HaveRight(money int) bool {
  50. return money < 5000
  51. }
  52. func (*DepManager) HandleFeeRequest(name string, money int) bool {
  53. if name == "tom" {
  54. fmt.Printf("Dep manager permit %s %d fee request\n", name, money)
  55. return true
  56. }
  57. fmt.Printf("Dep manager don't permit %s %d fee request\n", name, money)
  58. return false
  59. }
  60. type GeneralManager struct{}
  61. func NewGeneralManagerChain() *RequestChain {
  62. return &RequestChain{
  63. Manager: &GeneralManager{},
  64. }
  65. }
  66. func (*GeneralManager) HaveRight(money int) bool {
  67. return true
  68. }
  69. func (*GeneralManager) HandleFeeRequest(name string, money int) bool {
  70. if name == "ada" {
  71. fmt.Printf("General manager permit %s %d fee request\n", name, money)
  72. return true
  73. }
  74. fmt.Printf("General manager don't permit %s %d fee request\n", name, money)
  75. return false
  76. }

chain_test.go

  1. package chain
  2. func ExampleChain() {
  3. c1 := NewProjectManagerChain()
  4. c2 := NewDepManagerChain()
  5. c3 := NewGeneralManagerChain()
  6. c1.SetSuccessor(c2)
  7. c2.SetSuccessor(c3)
  8. var c Manager = c1
  9. c.HandleFeeRequest("bob", 400)
  10. c.HandleFeeRequest("tom", 1400)
  11. c.HandleFeeRequest("ada", 10000)
  12. c.HandleFeeRequest("floar", 400)
  13. // Output:
  14. // Project manager permit bob 400 fee request
  15. // Dep manager permit tom 1400 fee request
  16. // General manager permit ada 10000 fee request
  17. // Project manager don't permit floar 400 fee request
  18. }