awesome-patterns/behavioral/state/problem.go

119 lines
2.5 KiB
Go
Raw Normal View History

2019-05-03 05:48:46 +03:00
// 存疑部分.
//
// 这里是以玩家的健康状态为基准,影响生命回复和受到伤害的例子,有三个状态[健康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
// */
//}