awesome-patterns/behavioral/visitor/main.go
2019-05-04 10:03:01 +08:00

111 lines
2.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 访问者模式 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
*/
}