package visitor import "fmt" type Customer interface { Accept(Visitor) } type Visitor interface { Visit(Customer) } type EnterpriseCustomer struct { name string } 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) } } 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("serving enterprise customer %s\n", c.name) case *IndividualCustomer: fmt.Printf("serving individual customer %s\n", c.name) } } // only for enterprise type AnalysisVisitor struct{} func (*AnalysisVisitor) Visit(customer Customer) { switch c := customer.(type) { case *EnterpriseCustomer: fmt.Printf("analysis enterprise customer %s\n", c.name) } }