diff --git a/behavior/07_visitor/README.md b/behavior/07_visitor/README.md index d1584d7..4726cd7 100644 --- a/behavior/07_visitor/README.md +++ b/behavior/07_visitor/README.md @@ -1,8 +1,8 @@ # 访问者模式 - 访问者模式, + 访问者模式,常常1对N的情况处理,用于将数据结构和操作进行分离,访问者模式侧重Visitor一侧而不是被访问的一侧,可以方便的增加很多访问者,而是不是增加更多的访问对象. -访问者模式的目的是为了解耦对象和对象的使用和处理逻辑,一边提供资源,一边使用,也可以说是解耦生产出来的产品和产品消费者。 +访问者模式的目的是为了解耦对象和对象的使用和处理逻辑,一边提供资源,一边使用,也可以说是解耦生产出来的产品和产品消费者,同样用于分离操作的还有策略模式(strategy pattern),但两者存在侧重点不同. 一个石油的例子,油田提供石油,不同的客户将石油用到不同的地方,可能用于生产武器,可能用于提纯材料,生产服装,也可能只是用于只是用于提供动力,这些客户就是石油的不同visitor. diff --git a/behavior/07_visitor/visitor_game.go b/behavior/07_visitor/visitor_game.go new file mode 100644 index 0000000..6a85fc8 --- /dev/null +++ b/behavior/07_visitor/visitor_game.go @@ -0,0 +1,84 @@ +package visitor + +import "fmt" + +//IGameContext 游戏上下文 +type IGameContext interface { + Accept(IGameVisitor) +} + +//Player 代表其他玩家,因为用户角色需要和其他玩家交互 +type Player struct { + Name string + Level int +} + +//Accept 提供交互接口 +func (p Player) Accept(v IGameVisitor) { + v.VisitPlayer(p) +} + +//NPC 被方法对象 +type NPC struct { + Name string + IsImmortal bool //是否可以被打死 +} + +//Accept 接受聚能NPC访问能力的对象的访问 +func (n NPC) Accept(v IGameVisitor) { + v.VisitNPC(n) +} + +//SystemEnv 环境对象 +type SystemEnv struct { + Mark string //环境标识 + Version string //环境版本 +} + +//Accept 提供对环境的访问 +func (s SystemEnv) Accept(v IGameVisitor) { + v.VisitSystemEnv(s) +} + +//IGameVisitor 游戏提供的环境访问能力 +type IGameVisitor interface { + VisitPlayer(Player) + VisitNPC(NPC) + VisitSystemEnv(SystemEnv) +} + +// SettingVisitor 只提供Setting的能力 +type SettingVisitor struct{} + +//VisitPlayer 提供交互的第三方对象的信息 +func (SettingVisitor) VisitPlayer(p Player) { + fmt.Printf("Game Player: Name:%s ,Level:%d\n", p.Name, p.Level) +} + +//VisitNPC 提供NPC的信息 +func (SettingVisitor) VisitNPC(n NPC) { + fmt.Printf("Game NPC: Name:%s ,Immortal:%v\n", n.Name, n.IsImmortal) +} + +//VisitSystemEnv 提供游戏环境信息 +func (SettingVisitor) VisitSystemEnv(s SystemEnv) { + fmt.Printf("Game Env: Mark:%s ,Version:%s\n", s.Mark, s.Version) +} + +// Attacker 攻击者 +type Attacker struct{ name string } + +//VisitPlayer 攻击其他玩家 +func (a Attacker) VisitPlayer(p Player) { + fmt.Printf("%s Attack Player : %s\n", a.name, p.Name) +} + +//VisitNPC 攻击NPC +func (a Attacker) VisitNPC(n NPC) { + fmt.Printf("%s Attack NPC: %s\n", a.name, n.Name) +} + +//VisitSystemEnv 攻击环境,如石头,大门,墙壁 +func (a Attacker) VisitSystemEnv(s SystemEnv) { + fmt.Printf("Unsupported target %s\n", "game env") +} diff --git a/behavior/07_visitor/visitor_test.go b/behavior/07_visitor/visitor_test.go index 09056a2..1e9594c 100644 --- a/behavior/07_visitor/visitor_test.go +++ b/behavior/07_visitor/visitor_test.go @@ -21,13 +21,27 @@ func TestVisitor(t *testing.T) { } -func ExampleAnalysis() { - c := &CustomerCol{} - c.Add(NewEnterpriseCustomer("A company")) - c.Add(NewIndividualCustomer("bob")) - c.Add(NewEnterpriseCustomer("B company")) - c.Accept(&AnalysisVisitor{}) - // Output: - // analysis enterprise customer A company - // analysis enterprise customer B company +func TestGameVisitorsList(t *testing.T) { + + retriveSetting := SettingVisitor{} + attacker := Attacker{} + + pA := Player{"snow dance", 100} //角色名名:snow dance 100级 + pB := Player{"fire dragon", 120} + npc := NPC{"groceries", true} //卖杂货的NPC,是能被打死的 + env := SystemEnv{"made by china", "v1.2.11"} + + //游戏对象 + gameObjects := []IGameContext{pA, npc, env, pB} + + for _, v := range gameObjects { + v.Accept(retriveSetting) + } + + t.Log("\n---- !!!attack!!!- --") + + for _, v := range gameObjects { + v.Accept(attacker) + } + }