diff --git a/behavior/04_iterator/iterator_test.go b/behavior/04_iterator/iterator_test.go index ac2f580..6a9e7e7 100644 --- a/behavior/04_iterator/iterator_test.go +++ b/behavior/04_iterator/iterator_test.go @@ -35,7 +35,9 @@ func TestIterator(t *testing.T) { t.Log("pots count:", scenicArea.PotsCount()) - //切片变了,要重新获取 + //切片变了,所以要重新获取快照. + //如果想进一步了解看以这个例子: + //https://github.com/crazybber/go-fucking-exercise/blob/master/routine/slice_read_write_test.go potInterator = scenicArea.Iterator() potInterator.Reset() diff --git a/behavior/06_chain_of_responsibility/README.md b/behavior/06_chain_of_responsibility/README.md index a137620..d62c77c 100644 --- a/behavior/06_chain_of_responsibility/README.md +++ b/behavior/06_chain_of_responsibility/README.md @@ -3,13 +3,8 @@ 职责链模式用于动态组合一些行为,在go实现相对更为简单,行为模式中提到的option模式跟此模式很像,但是两者场景用例不同,op模式的行为常常用于对象初始化或者某一过程中设置参数,职责链主要作用在于动态组合行为链,以便处理特定的对象或者问题。 -中间件模式就是一个典型的职责链模式,一个对象,在中间件中层层传递,每一层都可以进行自己的处理。 +各大框架和语言中间件模式就是一个典型的职责链模式,一个对象,在中间件中层层传递,每一层都可以进行自己的处理。 +Golang中,由于函数对象存在使得职责链模式实现来更加灵活。 -Golang实现职责链模式时候,因为没有继承的支持,使用链对象包涵职责的方式,即: - -* 链对象包含当前职责对象以及下一个职责链。 -* 职责对象提供接口表示是否能处理对应请求。 -* 职责对象提供处理函数处理相关职责。 - -同时可在职责链类中实现职责接口相关函数,使职责链对象可以当做一般职责对象是用。 +现实生活中的一个申请的行政审批流程就是一个很好的职责链的例子,一个申请提交之后,要经过若干人对其进行处理。 diff --git a/behavior/06_chain_of_responsibility/responsibility_chain.go b/behavior/06_chain_of_responsibility/responsibility_chain.go index 78ecb8a..90ec23c 100644 --- a/behavior/06_chain_of_responsibility/responsibility_chain.go +++ b/behavior/06_chain_of_responsibility/responsibility_chain.go @@ -2,93 +2,148 @@ package chain import "fmt" -type Manager interface { - HaveRight(money int) bool - HandleFeeRequest(name string, money int) bool +//////////////////////////////// +//使用费用申请审批的例子 + +//FeeRequest 这就要要处理的对象 +type FeeRequest struct { + Mount int //申请的金额 + RequiredLevel int //审批人等级要求 + Name string //申请人 } -type RequestChain struct { - Manager - successor *RequestChain +//IApprove 审批动作 +type IApprove interface { + SetNext(next IApprove) //设置下一个审批流转 + HaveRight(level int) bool // + HandleApproval(request FeeRequest) bool } -func (r *RequestChain) SetSuccessor(m *RequestChain) { - r.successor = m +//////////////////////////////// +//实现方式1 +//////////////////////////////// + +//FeeRequestChainFlow 定义一个流程管理器 +type FeeRequestChainFlow struct { + approvers []IApprove //下一个流程节点 } -func (r *RequestChain) HandleFeeRequest(name string, money int) bool { - if r.Manager.HaveRight(money) { - return r.Manager.HandleFeeRequest(name, money) +//AddApprover 添加一个审批对象 +func (f *FeeRequestChainFlow) AddApprover(approver IApprove) { + f.approvers = append(f.approvers, approver) +} + +//RunApprovalFlow to deal request by chains +func (f *FeeRequestChainFlow) RunApprovalFlow(request FeeRequest) { + + for i := 0; i < len(f.approvers); i++ { + result := f.approvers[i].HandleApproval(request) + if !result { + //中间有一个环节出问题,流程就终止 + break + } } - if r.successor != nil { - return r.successor.HandleFeeRequest(name, money) - } - return false + } -func (r *RequestChain) HaveRight(money int) bool { +//////////////////////////////// +//实现方式2 +//////////////////////////////// + +//GM 总经理要审批 +type GM struct { + nextHandler IApprove //下一个流程节点 + level int +} + +//NewGM 总经理审批 +func NewGM() IApprove { + return &GM{level: 8} +} + +//SetNext 设置下一个审批节点 +func (g *GM) SetNext(next IApprove) { + g.nextHandler = next +} + +//HaveRight 处理审批所需要的权限级别 +func (g *GM) HaveRight(level int) bool { + return g.level > level +} + +//HandleApproval 进行审批 +func (g *GM) HandleApproval(request FeeRequest) bool { + if g.HaveRight(request.RequiredLevel) { + fmt.Printf("GM permit %s %d fee request\n", request.Name, request.Mount) + return true + } + fmt.Printf("GM Have right to approve %s %d fee request\n", request.Name, request.Mount) + //direct forward to Next One + if g.nextHandler != nil { + return g.nextHandler.HandleApproval(request) + } return true } -type ProjectManager struct{} - -func NewProjectManagerChain() *RequestChain { - return &RequestChain{ - Manager: &ProjectManager{}, - } +//CFO 需要审批 +type CFO struct { + nextHandler IApprove //下一个流程节点 + level int } -func (*ProjectManager) HaveRight(money int) bool { - return money < 500 +//NewCFO 对象 +func NewCFO() IApprove { + return &CFO{} + } -func (*ProjectManager) HandleFeeRequest(name string, money int) bool { - if name == "bob" { - fmt.Printf("Project manager permit %s %d fee request\n", name, money) - return true - } - fmt.Printf("Project manager don't permit %s %d fee request\n", name, money) - return false -} - -type DepManager struct{} - -func NewDepManagerChain() *RequestChain { - return &RequestChain{ - Manager: &DepManager{}, - } -} - -func (*DepManager) HaveRight(money int) bool { - return money < 5000 -} - -func (*DepManager) HandleFeeRequest(name string, money int) bool { - if name == "tom" { - fmt.Printf("Dep manager permit %s %d fee request\n", name, money) - return true - } - fmt.Printf("Dep manager don't permit %s %d fee request\n", name, money) - return false -} - -type GeneralManager struct{} - -func NewGeneralManagerChain() *RequestChain { - return &RequestChain{ - Manager: &GeneralManager{}, - } -} - -func (*GeneralManager) HaveRight(money int) bool { +//HaveRight CFO总是有权限的 +func (*CFO) HaveRight(RequiredLevel int) bool { return true } -func (*GeneralManager) HandleFeeRequest(name string, money int) bool { - if name == "ada" { - fmt.Printf("General manager permit %s %d fee request\n", name, money) +//SetNext 设置下一个审批节点 +func (c *CFO) SetNext(next IApprove) { + c.nextHandler = next +} + +//HandleApproval 进行审批 +func (c *CFO) HandleApproval(request FeeRequest) bool { + if request.Mount < 1e+10 { + fmt.Printf("CFO permit %s %d fee request\n", request.Name, request.Mount) return true } - fmt.Printf("General manager don't permit %s %d fee request\n", name, money) + // fmt.Printf("CFO permit %s %d fee request,But still need CEO \n", request.Name, request.Mount) + if c.nextHandler != nil { + return c.nextHandler.HandleApproval(request) + } + return true +} + +//CEO 需要审批 +type CEO struct{} + +//NewCEO 对象 +func NewCEO() IApprove { + return &CEO{} +} + +//HaveRight CEO总是有权限的 +func (*CEO) HaveRight(RequiredLevel int) bool { + return true +} + +//SetNext 设置下一个审批节点 +func (c *CEO) SetNext(next IApprove) { + //no thing to do +} + +//HandleApproval 进行审批 +func (*CEO) HandleApproval(request FeeRequest) bool { + if request.Mount < 1e+15 { + fmt.Printf("CEO permit %s %d fee request\n", request.Name, request.Mount) + return true + } + fmt.Printf("CEO deny %s %d fee request \n", request.Name, request.Mount) return false } diff --git a/behavior/06_chain_of_responsibility/responsibility_chain_test.go b/behavior/06_chain_of_responsibility/responsibility_chain_test.go index b0ddb39..cc3b841 100644 --- a/behavior/06_chain_of_responsibility/responsibility_chain_test.go +++ b/behavior/06_chain_of_responsibility/responsibility_chain_test.go @@ -1,23 +1,39 @@ package chain -func ExampleChain() { - c1 := NewProjectManagerChain() - c2 := NewDepManagerChain() - c3 := NewGeneralManagerChain() +import "testing" - c1.SetSuccessor(c2) - c2.SetSuccessor(c3) +func TestChainsOfResponsibilityInApprovementList(t *testing.T) { - var c Manager = c1 + request := FeeRequest{ + Name: "sophia", + Mount: 1e+13, + RequiredLevel: 8, + } - c.HandleFeeRequest("bob", 400) - c.HandleFeeRequest("tom", 1400) - c.HandleFeeRequest("ada", 10000) - c.HandleFeeRequest("floar", 400) - // Output: - // Project manager permit bob 400 fee request - // Dep manager permit tom 1400 fee request - // General manager permit ada 10000 fee request - // Project manager don't permit floar 400 fee request + flow := &FeeRequestChainFlow{} + + gm1 := &GM{level: 7} + + cfo1 := &CFO{level: 9} + + flow.AddApprover(gm1) + flow.AddApprover(cfo1) + + flow.RunApprovalFlow(request) + + // request = FeeRequest{ + // Name: "peter", + // Mount: 1e+13, + // RequiredLevel: 8, + // } + + // ceo := &CEO{level: 10} + // flow.AddApprover(ceo) + + // flow.RunApprovalFlow(request) + +} + +func TestChainsOfResponsibilityInApprovementLink(t *testing.T) { }