23、 Golang 设计模式:23_访问者模式

1、介绍

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

访问者模式(Visitor)是一种操作一组对象的操作,它的目的是不改变对象的定义,但允许新增不同的访问者,来定义新的操作。

访问者模式的设计比较复杂,如果我们查看GoF原始的访问者模式,它是这么设计的:

  ┌─────────┐       ┌───────────────────────┐
   │ Client  │─ ─ ─ >│        Visitor        │
   └─────────┘       ├───────────────────────┤
        │            │visitElementA(ElementA)│
                     │visitElementB(ElementB)│
        │            └───────────────────────┘
                                 ▲
        │                ┌───────┴───────┐
                         │               │
        │         ┌─────────────┐ ┌─────────────┐
                  │  VisitorA   │ │  VisitorB   │
        │         └─────────────┘ └─────────────┘
        ▼
┌───────────────┐        ┌───────────────┐
│ObjectStructure│─ ─ ─ ─>│    Element    │
├───────────────┤        ├───────────────┤
│handle(Visitor)│        │accept(Visitor)│
└───────────────┘        └───────────────┘
                                 ▲
                        ┌────────┴────────┐
                        │                 │
                ┌───────────────┐ ┌───────────────┐
                │   ElementA    │ │   ElementB    │
                ├───────────────┤ ├───────────────┤
                │accept(Visitor)│ │accept(Visitor)│
                │doA()          │ │doB()          │
                └───────────────┘ └───────────────┘

在访问者模式中,主要包括下面几个角色:

2、示例

示例代码:

 package main

import "fmt"

type Customer interface {
    Accept(visitor Visitor)
}
type Visitor interface {
    Visit(customer Customer)
}

//客户群
type CustomerCol struct {
    customers []Customer
}

func (c *CustomerCol) Add(customer Customer) {
    c.customers = append(c.customers, customer)
}
func (c *CustomerCol) Accept(visitor Visitor) {
    for _, customer := range c.customers {
        customer.Accept(visitor)
    }
}

//企业级客户
type EnterpriseCustomer struct {
    name string
}

func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
    return &EnterpriseCustomer{
        name: name,
    }
}
func (c *EnterpriseCustomer) Accept(visitor Visitor) {
    visitor.Visit(c)

}

//个人客户
type IndividualCustomer struct {
    name string
}

func NewIndividualCustomer(name string) *IndividualCustomer {
    return &IndividualCustomer{
        name: name,
    }
}
func (c *IndividualCustomer) Accept(visitor Visitor) {
    visitor.Visit(c)

}

//访问器
type ServiceRequestVisitor struct{}

func (*ServiceRequestVisitor) Visit(customer Customer) {
    switch c := customer.(type) {
    case *EnterpriseCustomer:
        fmt.Printf("服务企业级客户:%s\n", c.name)
    case *IndividualCustomer:
        fmt.Printf("服务个人客户:%s\n", c.name)
    }
}

type AnalysisVisitor struct{}

func (*AnalysisVisitor) Visit(customer Customer) {
    switch c := customer.(type) {
    case *EnterpriseCustomer:
        fmt.Printf("分析企业级客户:%s\n", c.name)
    }
}
func main() {
    c:=&CustomerCol{}
    c.Add(NewEnterpriseCustomer("中电科"))
    c.Add(NewEnterpriseCustomer("绿盟"))
    c.Add(NewIndividualCustomer("jiangzhou"))
    c.Accept(&ServiceRequestVisitor{})
    fmt.Println("==========")
    c1:=&CustomerCol{}
    c1.Add(NewEnterpriseCustomer("中电科"))
    c1.Add(NewIndividualCustomer("jiangzhou"))
    c1.Add(NewEnterpriseCustomer("绿盟"))
    c1.Accept(&AnalysisVisitor{})

}

UML图: