diff --git a/README.md b/README.md index 6b76f10..3850325 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ A curated collection of idiomatic design & application patterns for Go language. | [Memento](/behavioral/memento/main.go) | Generate an opaque token that can be used to go back to a previous state | ✔ | | [Observer](/behavioral/observer.md) | Provide a callback for notification of events/changes to data | ✔ | | [Registry](/behavioral/registry.md) | Keep track of all subclasses of a given class | ✘ | -| [State](/behavioral/state.md) | Encapsulates varying behavior for the same object based on its internal state | ✔ | +| [State](/behavioral/state/main.go) | Encapsulates varying behavior for the same object based on its internal state | ✔ | | [Strategy](/behavioral/strategy.md) | Enables an algorithm's behavior to be selected at runtime | ✔ | -| [Template](/behavioral/template.md) | Defines a skeleton class which defers some methods to subclasses | ✔ | -| [Visitor](/behavioral/visitor.md) | Separates an algorithm from an object on which it operates | ✘ | +| [Template](/behavioral/template/main.go) | Defines a skeleton class which defers some methods to subclasses | ✔ | +| [Visitor](/behavioral/visitor/main.go) | Separates an algorithm from an object on which it operates | ✔ | ## Synchronization Patterns diff --git a/behavioral/visitor/main.go b/behavioral/visitor/main.go new file mode 100644 index 0000000..474c668 --- /dev/null +++ b/behavioral/visitor/main.go @@ -0,0 +1,110 @@ +// 访问者模式 visitor pattern. +// 该模式用于将数据结构和操作进行分离,同样用于分离操作的还有策略模式(strategy pattern),但两者存在侧重点的不同. +// 访问者模式侧重于扩展访问的方法类型,是为了对某一个类及其子类的访问方式进行扩展,允许增加更多不同的访问者,但不宜增加更多的Host. +// 以下以实体A(仅有玩家、NPC、物体三类)被访问(查看信息、发起挑战等,此处可扩展)的过程 +package main + +import "log" + +// 如果这里有更多的新类型Host需要扩展,则不宜使用访问者模式 +type Host interface { + Accept(Visitor) +} + +type PlayerHost struct { + Name string + Level int +} + +func (p PlayerHost)Accept(v Visitor){ + v.VisitPlayer(p) +} + +type NPCHost struct { + Name string + IsImmortal bool +} + +func (n NPCHost)Accept(v Visitor){ + v.VisitNPC(n) +} + +type ObjectHost struct { + Name string + Price int +} + +func (o ObjectHost)Accept(v Visitor){ + v.VisitObject(o) +} + +type Visitor interface { + VisitPlayer(PlayerHost) + VisitNPC(NPCHost) + VisitObject(ObjectHost) +} + +// 访问者允许有不同类型的访问者 +// 仅查看信息的访问者 +type InfoVisitor struct {} + +func (InfoVisitor) VisitPlayer(p PlayerHost) { + log.Printf("Player -> Name:%s ,Level:%d\n" ,p.Name ,p.Level) +} + +func (InfoVisitor) VisitNPC(n NPCHost) { + log.Printf("NPC -> Name:%s ,Immortal:%v\n" ,n.Name ,n.IsImmortal) +} + +func (InfoVisitor) VisitObject(o ObjectHost) { + log.Printf("Object -> Name:%s ,Price:%d\n" ,o.Name ,o.Price) +} + +// 发起攻击的访问者 +type AggressiveVisitor struct {} + +func (AggressiveVisitor) VisitPlayer(p PlayerHost) { + log.Printf("Attack %s\n" ,p.Name) +} + +func (AggressiveVisitor) VisitNPC(n NPCHost) { + log.Printf("Attack NPC %s\n" ,n.Name) +} + +func (AggressiveVisitor) VisitObject(o ObjectHost) { + log.Printf("Unsupported target %s\n" ,o.Name) +} + +func main(){ + infoVst := InfoVisitor{} + agrVst := AggressiveVisitor{} + + pA := PlayerHost{"icg" ,1} + pB := PlayerHost{"sz" ,2} + npc := NPCHost{"nyn" ,true} + obj := ObjectHost{"cake" ,19} + + hostList := []Host{pA ,npc ,obj ,pB} + + for _ ,v := range hostList{ + v.Accept(infoVst) + } + println() + for _ ,v := range hostList{ + v.Accept(agrVst) + } + /* + output: + 2019/05/04 10:00:49 Player -> Name:icg ,Level:1 + 2019/05/04 10:00:49 NPC -> Name:nyn ,Immortal:true + 2019/05/04 10:00:49 Object -> Name:cake ,Price:19 + 2019/05/04 10:00:49 Player -> Name:sz ,Level:2 + + 2019/05/04 10:00:49 Attack icg + 2019/05/04 10:00:49 Attack NPC nyn + 2019/05/04 10:00:49 Unsupported target cake + 2019/05/04 10:00:49 Attack sz + */ + +} +