finish visitor pattern

This commit is contained in:
Edward 2020-05-04 16:12:01 +08:00
parent cbdb15f07f
commit 0c69fdb726
3 changed files with 74 additions and 72 deletions

View File

@ -1,6 +1,14 @@
# 访问者模式 # 访问者模式
访问者模式可以给一系列对象透明的添加功能并且把相关代码封装到一个类中。 访问者模式,
对象只要预留访问者接口`Accept`则后期为对象添加功能的时候就不需要改动对象。 访问者模式的目的是为了解耦对象和对象的使用和处理逻辑,一边提供资源,一边使用,也可以说是解耦生产出来的产品和产品消费者。
一个石油的例子油田提供石油不同的客户将石油用到不同的地方可能用于生产武器可能用于提纯材料生产服装也可能只是用于只是用于提供动力这些客户就是石油的不同visitor.
客户买石油的时候都要遵循油田的购买方式否则就不卖给你这个特定的购买方式就是指Visitor模式中常说的Accept方法。
打游戏是个不错的例子。
玩家角色需要跟NPC其他玩家以及游戏环境交换这些都是Visit的过程.

View File

@ -2,73 +2,58 @@ package visitor
import "fmt" import "fmt"
type Customer interface { ////////////////////////////////
Accept(Visitor) //使用石油的例子
//IGasResource 作为资源提供接口
type IGasResource interface {
Accept(IGasVisitor)
} }
type Visitor interface { //gas 汽油
Visit(Customer) type gas struct {
density int
} }
type EnterpriseCustomer struct { //IGasVisitor 访问者接口
type IGasVisitor interface {
Visit(gas)
}
//Accept 接待汽油客户
func (g gas) Accept(visitor IGasVisitor) {
visitor.Visit(g)
}
//diesel 柴油
type diesel struct {
energy int
}
//IDieselVisitor 访问者接口
type IDieselVisitor interface {
Visit(diesel)
}
//Accept 提供柴油
func (d diesel) Accept(visitor IDieselVisitor) {
visitor.Visit(d)
}
//militaryFactory 军工厂,消费石油,制造务器
type militaryFactory struct {
name string name string
} }
type CustomerCol struct { //Visit 军工厂只够买柴油,制造武器
customers []Customer func (m *militaryFactory) Visit(d diesel) {
fmt.Println("militaryFactory: use diesel with inner energy", d.energy)
} }
func (c *CustomerCol) Add(customer Customer) { // clothFactory 服务装类工厂,购买汽油,制造化纤物品
c.customers = append(c.customers, customer) type clothFactory struct{}
}
//Visit 购买汽油
func (c *CustomerCol) Accept(visitor Visitor) { func (c *clothFactory) Visit(g gas) {
for _, customer := range c.customers { fmt.Println("clothFactory: use gas with density", g.density)
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)
}
} }

View File

@ -1,15 +1,24 @@
package visitor package visitor
func ExampleRequestVisitor() { import "testing"
c := &CustomerCol{}
c.Add(NewEnterpriseCustomer("A company")) func TestVisitor(t *testing.T) {
c.Add(NewEnterpriseCustomer("B company"))
c.Add(NewIndividualCustomer("bob")) //汽油提供给,制衣工厂
c.Accept(&ServiceRequestVisitor{}) g := gas{density: 100}
// Output:
// serving enterprise customer A company //柴油,提供给军工厂
// serving enterprise customer B company d := diesel{energy: 897}
// serving individual customer bob
//购买石油的客户
m := &militaryFactory{}
c := &clothFactory{}
g.Accept(c)
d.Accept(m)
} }
func ExampleAnalysis() { func ExampleAnalysis() {