以嵌入组合的方式实现控制反转 IoC:
控制反转
是一种解耦思想,将原本耦合在业务逻辑
中的控制逻辑
单独拆出来实现,不再让业务逻辑
在处理业务的同时还要去实现控制逻辑
,而是专注处理业务。在业务逻辑
代码中耦合进控制逻辑
,会导致在编写业务逻辑时需要处理业务之外的事,而且控制逻辑
耦合进业务中,只适用于当前业务逻辑,无法被复用
。
go
// 以嵌入组合的方式实现控制反转 IoC
package main
import (
"errors"
"fmt"
)
// 2.被要求:新增一 'undo 后悔' 功能。
// 3.解决办法:定义单独(通用的)控制逻辑,别的数据结构也可能会用到
// 即:控制逻辑封装在 Undo 中,业务逻辑 IntSet 只关心处理整型数据
type Undo []func() // 函数切片
func (undo *Undo) Add(fn func()) { //undo入栈
*undo = append(*undo, fn)
}
func (undo *Undo) Undo() error {
functions := *undo
if len(functions) == 0 {
return errors.New("No functions to undo")
}
index := len(functions) - 1
if fn := functions[index]; fn != nil {
fn()
functions[index] = nil // 垃圾回收
}
*undo = functions[:index] // undo出栈操作
return nil
}
// ----------------------------------------------
type IntSet struct {
data map[int]bool // 1.原本的处理整形数据的结构
undo Undo // 3.解决办法:并在此处嵌入一个 Undo 结构,间接实现 undo 功能
}
func NewIntSet() IntSet {
return IntSet{data: make(map[int]bool)}
}
func (set *IntSet) Add(x int) {
// set.data[x] = true //原来逻辑
// 改为
if !set.Contains(x) {
set.data[x] = true
set.undo.Add(func() { set.Delete(x) })
} else {
set.undo.Add(nil)
}
}
func (set *IntSet) Delete(x int) {
// delete(set.data, x) //原来逻辑
//改为
if set.Contains(x) {
delete(set.data, x)
set.undo.Add(func() { set.Add(x) })
} else {
set.undo.Add(nil)
}
}
func (set *IntSet) Contains(x int) bool {
return set.data[x]
}
// 3.新增
func (set *IntSet) Undo() error {
return set.undo.Undo()
}
// ----------------------------------------------
func main() {
a := NewIntSet()
for i := 1; i < 11; i++ {
a.Add(i)
}
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 4:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(2))
a.Delete(2)
fmt.Printf("%v\n", a) //map[1:true 3:true 4:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(2))
a.Undo()
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 4:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(2))
fmt.Printf("%v\n", a.Contains(4))
a.Delete(4)
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(4))
a.Delete(7)
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 5:true 6:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(7))
a.Undo()
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(7))
a.Undo()
fmt.Printf("%v\n", a) //map[1:true 2:true 3:true 4:true 5:true 6:true 7:true 8:true 9:true 10:true]
fmt.Printf("%v\n", a.Contains(4))
}