Golang中的动作组合实践与应用
Golang中的动作组合实践与应用
大家好,我是Go语言的新手。我想尝试一下由动作组合而成的类。例如,一个玩家可以walk()和fly(),但也许一个怪物只能walk()。
在这种情况下,walk()和fly()方法都需要访问玩家的位置,所以我想出了以下代码。然而,我想知道这是否真正符合Go语言的惯用法。我不太喜欢的一点是,同一个指针被多个对象所拥有。
// You can edit this code!
// Click here and start typing.
package main
import "fmt"
type PositionComponent struct {
x int
y int
}
type Positionable interface {
GetPositionComponent() *PositionComponent
SetPositionComponent(x int, y int)
}
func (p *PositionComponent) GetPositionComponent() *PositionComponent {
return p
}
func (p *PositionComponent) SetPositionComponent(x int, y int) {
p.x = x
p.y = y
}
type Walker struct {
Positionable
}
type Flyer struct {
Positionable
}
func (w *Walker) walk() {
w.GetPositionComponent().x += 1
fmt.Printf("Walked: %s\n", w.GetPositionComponent())
}
func (w *Flyer) fly() {
w.GetPositionComponent().y += 1
fmt.Printf("Flew: %s\n", w.GetPositionComponent())
}
type Player struct {
*PositionComponent
Walker
Flyer
}
func main() {
pComp := PositionComponent{2, 2}
p := Player{&pComp, Walker{&pComp}, Flyer{&pComp}}
p.walk()
p.fly()
fmt.Println(p.PositionComponent)
}
更多关于Golang中的动作组合实践与应用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中的动作组合实践与应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现动作组合时,更惯用的做法是使用结构体嵌入和接口组合。你的代码方向正确,但可以简化。以下是改进版本:
package main
import "fmt"
type Position struct {
X int
Y int
}
func (p *Position) Move(x, y int) {
p.X += x
p.Y += y
}
func (p Position) String() string {
return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}
type Walker struct {
*Position
}
func (w *Walker) Walk() {
w.Move(1, 0)
fmt.Printf("Walked to %s\n", w.Position)
}
type Flyer struct {
*Position
}
func (f *Flyer) Fly() {
f.Move(0, 1)
fmt.Printf("Flew to %s\n", f.Position)
}
type Player struct {
*Position
Walker
Flyer
}
type Monster struct {
*Position
Walker
}
func main() {
// Player可以走和飞
playerPos := &Position{2, 2}
player := Player{
Position: playerPos,
Walker: Walker{playerPos},
Flyer: Flyer{playerPos},
}
player.Walk()
player.Fly()
fmt.Printf("Player final position: %s\n", player.Position)
// Monster只能走
monsterPos := &Position{5, 5}
monster := Monster{
Position: monsterPos,
Walker: Walker{monsterPos},
}
monster.Walk()
// monster.Fly() // 编译错误:Monster没有Fly方法
fmt.Printf("Monster final position: %s\n", monster.Position)
// 验证位置共享
fmt.Printf("Player X: %d, Monster X: %d\n", player.X, monster.X)
}
另一种更简洁的实现方式,使用接口:
package main
import "fmt"
type Mover interface {
Move(x, y int)
Position() (int, int)
}
type Position struct {
x, y int
}
func (p *Position) Move(x, y int) {
p.x += x
p.y += y
}
func (p *Position) Position() (int, int) {
return p.x, p.y
}
type WalkBehavior struct {
Mover
}
func (w *WalkBehavior) Walk() {
w.Move(1, 0)
x, y := w.Position()
fmt.Printf("Walked to (%d, %d)\n", x, y)
}
type FlyBehavior struct {
Mover
}
func (f *FlyBehavior) Fly() {
f.Move(0, 1)
x, y := f.Position()
fmt.Printf("Flew to (%d, %d)\n", x, y)
}
type Player struct {
*Position
*WalkBehavior
*FlyBehavior
}
func NewPlayer(x, y int) *Player {
pos := &Position{x, y}
return &Player{
Position: pos,
WalkBehavior: &WalkBehavior{pos},
FlyBehavior: &FlyBehavior{pos},
}
}
type Monster struct {
*Position
*WalkBehavior
}
func NewMonster(x, y int) *Monster {
pos := &Position{x, y}
return &Monster{
Position: pos,
WalkBehavior: &WalkBehavior{pos},
}
}
func main() {
player := NewPlayer(2, 2)
player.Walk()
player.Fly()
monster := NewMonster(5, 5)
monster.Walk()
}
第一个示例展示了直接的结构体嵌入,第二个示例使用接口提供了更好的抽象。两种方式都避免了显式的Get/Set方法,更符合Go的惯用法。多个对象共享同一个指针在Go中是常见的,只要注意生命周期管理即可。

