mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-28 15:56:04 +03:00
119 lines
2.5 KiB
Go
119 lines
2.5 KiB
Go
// 存疑部分.
|
||
//
|
||
// 这里是以玩家的健康状态为基准,影响生命回复和受到伤害的例子,有三个状态[健康HealthyState|受伤WoundedState|死亡DeadState].
|
||
// 和main.go中的跷跷板例子由行为驱动状态变化不同.以下例子的行为是受到数据影响的,结果就是达不到完全消除if-else的效果
|
||
//
|
||
// 疑问:
|
||
// 1. 很多地方说状态模式可以消除if-else,事实上要做到自行的状态切换很多时候还是会用到if-else,这里的消除应当是指
|
||
// 将巨大的条件语句拆分开(?)
|
||
// 2. 还是说这种由数据决定状态的事务逻辑下不适合使用状态模式
|
||
package main
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
)
|
||
|
||
// state
|
||
type PlayerState interface {
|
||
Heal(p *Player) error
|
||
Hurt(p *Player ,dmg int)
|
||
}
|
||
|
||
type HealthyState struct {}
|
||
|
||
func (h HealthyState)Heal(p *Player) error{
|
||
return nil
|
||
}
|
||
|
||
func (h HealthyState)Hurt(p *Player ,dmg int){
|
||
if dmg > 0 && dmg < p.MaxHealth{
|
||
p.Health = p.Health - dmg
|
||
p.State = WoundedState{}
|
||
}else if dmg > p.MaxHealth{
|
||
p.Health = 0
|
||
p.State = DeadState{}
|
||
}
|
||
}
|
||
|
||
type WoundedState struct {}
|
||
|
||
func (WoundedState)Heal(p *Player) error{
|
||
if p.Health >= p.MaxHealth - 5{
|
||
fmt.Printf("healing from %d to %d\n" ,p.Health ,p.MaxHealth)
|
||
p.State = HealthyState{}
|
||
p.Health = p.MaxHealth
|
||
}else{
|
||
fmt.Printf("healing from %d to %d\n" ,p.Health ,p.Health+5)
|
||
p.Health = p.Health + 5
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (h WoundedState)Hurt(p *Player ,dmg int){
|
||
if p.Health > dmg{
|
||
p.Health = p.Health - dmg
|
||
}else {
|
||
p.State = DeadState{}
|
||
p.Health = 0
|
||
}
|
||
}
|
||
|
||
type DeadState struct {}
|
||
|
||
func (DeadState)Heal(P *Player) error{
|
||
return errors.New("you are dead")
|
||
}
|
||
|
||
func (DeadState)Hurt(P *Player ,dmg int){}
|
||
|
||
// context
|
||
type Player struct {
|
||
Health int
|
||
MaxHealth int
|
||
State PlayerState
|
||
}
|
||
|
||
func (p *Player)HealPlayer()error{
|
||
return p.State.Heal(p)
|
||
}
|
||
|
||
func (p *Player)HurtPlayer(damage int){
|
||
fmt.Printf("damage %d\n" ,damage)
|
||
p.State.Hurt(p ,damage)
|
||
}
|
||
|
||
//func main(){
|
||
// player := &Player{
|
||
// Health:100,
|
||
// MaxHealth:100,
|
||
// State:HealthyState{},
|
||
// }
|
||
//
|
||
// rand.Seed(time.Now().UnixNano())
|
||
// for i:=0 ;i<10 ;i++{
|
||
// if err := player.HealPlayer();err != nil{
|
||
// fmt.Println(err)
|
||
// break
|
||
// }
|
||
// player.HurtPlayer(rand.Intn(30))
|
||
// }
|
||
// /*
|
||
// output:
|
||
// damage 28
|
||
// healing from 72 to 77
|
||
// damage 29
|
||
// healing from 48 to 53
|
||
// damage 15
|
||
// healing from 38 to 43
|
||
// damage 1
|
||
// healing from 42 to 47
|
||
// damage 19
|
||
// healing from 28 to 33
|
||
// damage 27
|
||
// healing from 6 to 11
|
||
// damage 16
|
||
// you are dead
|
||
// */
|
||
//}
|