组合模式
最后更新于:2022-04-02 02:35:41
[TOC]
## 组合模式
一个具有层级关系的对象由一系列拥有父子关系的对象通过树形结构组成(类似树形式的组件)
> [参考](http://tigerb.cn/2020/04/06/go-patterns-component/?utm_source=tuicool&utm_medium=referral)
>
![UTOOLS1589241072846.png](http://yanxuan.nosdn.127.net/5a119611178cd768ade28de3c7ad4bc9.png)
```
成员属性
ChildComponents: 子组件列表 -> 稳定不变的
成员方法
Mount: 添加一个子组件 -> 稳定不变的
Remove: 移除一个子组件 -> 稳定不变的
Do: 执行组件&子组件 -> 变化的
```
main.go
```
package main
import (
"context"
"fmt"
"reflect"
"runtime"
)
// Context 上下文
//type Context struct{}
// IComponent 组件接口
type IComponent interface {
// 添加一个子组件
Mount(c IComponent, components ...IComponent) error
// 移除一个子组件
Remove(c IComponent) error
// 执行组件&子组件
Do(ctx context.Context) error
}
// BaseComponent 基础组件
// 实现Add:添加一个子组件
// 实现Remove:移除一个子组件
type BaseComponent struct {
// 子组件列表
ChildComponents []IComponent
}
// Mount 挂载一个子组件
func (bc *BaseComponent) Mount(c IComponent, components ...IComponent) (err error) {
bc.ChildComponents = append(bc.ChildComponents, c)
if len(components) == 0 {
return
}
bc.ChildComponents = append(bc.ChildComponents, components...)
return
}
// Remove 移除一个子组件
func (bc *BaseComponent) Remove(c IComponent) (err error) {
if len(bc.ChildComponents) == 0 {
return
}
for k, childComponent := range bc.ChildComponents {
if c == childComponent {
fmt.Println(runFuncName(), "移除:", reflect.TypeOf(childComponent))
bc.ChildComponents = append(bc.ChildComponents[:k], bc.ChildComponents[k+1:]...)
}
}
return
}
// Do 执行组件&子组件
func (bc *BaseComponent) Do(ctx context.Context) (err error) {
// Do nothing
return
}
// ChildsDo 执行子组件
func (bc *BaseComponent) ChildsDo(ctx context.Context) (err error) {
// 执行子组件
for _, childComponent := range bc.ChildComponents {
if err = childComponent.Do(ctx); err != nil {
return err
}
}
return
}
type All struct {
BaseComponent
}
type A1 struct {
BaseComponent
}
func (a *A1) Do(ctx context.Context) (err error) {
fmt.Println(runFuncName(), "A1...")
a.ChildsDo(ctx)
return
}
type A11 struct {
BaseComponent
}
func (a *A11) Do(ctx context.Context) (err error) {
fmt.Println(runFuncName(), "A11...")
a.ChildsDo(ctx)
return
}
type A12 struct {
BaseComponent
}
func (a *A12) Do(ctx context.Context) (err error) {
fmt.Println(runFuncName(), "A12...")
a.ChildsDo(ctx)
return
}
type B1 struct {
BaseComponent
}
func (a *B1) Do(ctx context.Context) (err error) {
fmt.Println(runFuncName(), "B1...")
a.ChildsDo(ctx)
return
}
type C1 struct {
BaseComponent
}
func (a *C1) Do(ctx context.Context) (err error) {
fmt.Println(runFuncName(), "C1...")
a.ChildsDo(ctx)
fmt.Printf("%+v\n", ctx.Value("a"))
return
}
func main() {
// 初始化订单结算页面 这个大组件
all :=&All{}
a1 := &A1{}
a1.Mount(&A11{}, &A12{})
b1 := &B1{}
all.Mount(a1, b1,&C1{})
// 只能删除本身的子组件
all.Remove(b1)
// 开始构建页面组件数据
ctx := context.WithValue(context.Background(), "a", "b")
all.ChildsDo(ctx)
}
// 获取正在运行的函数名
func runFuncName() string {
pc := make([]uintptr, 1)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return f.Name()
}
```
';