综合题
本内容选自 k8s (opens new window)
k8s visitor + 修饰器 + pipeline
这种写法,以 k8s 的 visitor 作为主要的实现方法,修饰器和 pipeline 作为辅助的实现手法
首先我们实现这段代码的目的是为了将数据结构和算法分离,并且,我们希望每段的算法处理数据结构的一部分。
// 行为
type visitorFunc func(*info, error) error
// 抽象层
type Visitor interface {
Visit(visitorFunc) error
}
// 数据
type info struct {
name string
year int
addr string
}
func (i *info) Visit(v visitorFunc) error {
return v(i, nil)
}
我们基础部分已经写好了,这样就具备了基本的 visitor 的模式,接下来我们来写算法的实现
// 多态
type OneDeal struct {
visitor Visitor
}
func (o OneDeal) Visit(v visitorFunc) error {
return o.visitor.Visit(func(i *info, err error) error {
e := v(i, err)
fmt.Println("one deal", i.name)
return e
})
}
type twoDeal struct {
visitor Visitor
}
func (o twoDeal) Visit(v visitorFunc) error {
return o.visitor.Visit(func(i *info, err error) error {
e := v(i, err)
fmt.Println("two deal", i.addr, i.year)
return e
})
}
当算法搞定以后,我们在 main 调用一下:
func main() {
o := &info{}
var v Visitor = o
v = OneDeal{v}
v = twoDeal{v}
l := func(i *info, err error) error {
i.name = "liu"
i.year = 2020
i.addr = "beijing"
return nil
}
v.Visit(l)
}
可以看到,visitor,pipline,以及修饰器的模式都运用了
- visitor:上面一个 type func,下面的 interface,连在一起就是 visitor 模式
- pipline:可以看到 visitor 的变量在不停的传递,然后调用的时候肯定会一直的调用不同的 visit func 函数,这就是 pipline
- 修饰器:不同的 function,在不停的增加内容,并且输出的还是这个 function,这就是修饰器模式
可以看到,这个模式下,visitor 是主要的模式,其他的模式都是因这个模式而附带的效果,所以也可以说,visitor 自带 pipline 和修饰器模式,所以这种写法就单单的只是 visitor 而已。
接下来,我们将修饰器模式作为主要的模式,另外加上 visitor 和 pipline
修饰器 + k8s visitor + pipeline
同样的我们需要先构造一个 visitor 系统
type VisitorFunc func(*Info, error) error
type Visitor interface {
Visit(VisitorFunc) error
}
type Info struct {
name string
year int
addr string
}
func (i *Info) Visit(v VisitorFunc) error {
return v(i, nil)
}
接下来我们创建一个修饰器系统
type VisitorBox struct {
visitor Visitor // 行为
visitorFucs []VisitorFunc // 代表数据的桥梁
}
func NewVisitorBox(v Visitor, fn ...VisitorFunc) Visitor {
if len(fn) == 0 {
return v
}
return VisitorBox{visitorFucs: fn, visitor: v}
}
func (vi VisitorBox) Visit(v VisitorFunc) error {
return vi.visitor.Visit(func(i *Info, e error) error {
if e != nil {
return e
}
if err := v(i, nil); err != nil {
return err
}
for k := range vi.visitorFucs {
if err := vi.visitorFucs[k](i, nil); err != nil {
return err
}
}
return nil
})
}
接下来让我们调用一下
func main() {
loadFile := func(info *Info, err error) error {
info.name = "li"
info.year = 10
info.addr = "bj"
return nil
}
func1 := func(info *Info, err error) error {
fmt.Println(info.name)
return nil
}
func2 := func(info *Info, err error) error {
fmt.Println(info.year)
return nil
}
func3 := func(info *Info, err error) error {
fmt.Println(info.addr)
return nil
}
info := &Info{}
var v Visitor = info
v = NewVisitorBox(v, func1, func2, func3)
v.Visit(loadFile)
}
这种写法跟上面的写法改变之处在于创建了一个修饰器的 struct,并且装在了一个 pipline 的切片,然后我们就不用依次调用不同的算法结构体了,我们只需要在 new box 的时候将要执行的函数放入进去即可。