Is it possible to refactor the following code to eliminate the duplication?
I want my GameObject implement the logic for "update" task invoking different update handlers (like my "AfterUpdate"). The current version works, but there are two implementations of "Update" and they are equal. AfterUpdate invoked on GameObject should operate on its properties, AfterUpdate invoked on HeroGameObject should have access to HeroGameObject's properties (like "health" for example).
What can I do better? Thank you.
package main
import "fmt"
type Point struct {
x, y int
}
///////////////////////
type GameObject struct {
Point
title string
status int
ticks float32
spriteIndex int
}
func (g *GameObject) Update() {
if g.ticks == 0 {
g.spriteIndex++
g.AfterUpdate()
}
}
func (g *GameObject) AfterUpdate() {
g.status = 0 //suppose it does something meaningful
fmt.Println("GameObject afterUpdate handler invoked")
}
///////////////////////
type HeroGameObject struct {
GameObject
health float32
}
func (h *HeroGameObject) Update() {
if h.ticks == 0 {
h.spriteIndex++
h.AfterUpdate()
}
}
func (h *HeroGameObject) AfterUpdate() {
h.health-- //suppose it does something meaningful but *different*, using its own properties, for example "health"
fmt.Println("HeroGameObject afterUpdate handler invoked")
}
///////////////////////
func main() {
gameObject := &GameObject{
Point: Point{
x: 0,
y: 0,
},
title: "dummy object",
status: 0,
ticks: 0,
spriteIndex: 0,
}
heroObject := &HeroGameObject{
GameObject: GameObject{
Point: Point{
x: 0,
y: 0,
},
title: "hero object",
status: 0,
ticks: 0,
spriteIndex: 0,
},
health: 0,
}
gameObject.Update()
heroObject.Update()
}
The output:
GameObject afterUpdate handler invoked
HeroGameObject afterUpdate handler invoked
UPDATED I've come up with the following solution and I wonder what do you think:
package main
import "fmt"
type Point struct {
x, y int
}
///////////////////////
type IHandler interface {
afterUpdate()
}
type GameObject struct {
Point
title string
status int
ticks float32
spriteIndex int
handler IHandler
}
func (g *GameObject) SetHandler(h IHandler) {
g.handler = h
}
func (g *GameObject) Update() {
if g.ticks == 0 {
g.spriteIndex++
if g.handler != nil {
g.handler.afterUpdate()
}
}
}
//actually it is IHandler specific implementation number one
func (g *GameObject) afterUpdate() {
g.status = 0 //suppose it does something meaningful
fmt.Println("GameObject afterUpdate handler invoked")
}
///////////////////////
type HeroGameObject struct {
GameObject
health float32
}
// note, this method is commented out
/*
func (h *HeroGameObject) Update() {
if h.ticks == 0 {
h.spriteIndex++
h.AfterUpdate()
}
}*/
//actually it is IHandler specific implementation number two
func (h *HeroGameObject) afterUpdate() {
h.health-- //suppose it does something meaningful but *different*, using its own properties, for example "health"
fmt.Println("HeroGameObject afterUpdate handler invoked")
}
///////////////////////
func main() {
gameObject := &GameObject{
Point: Point{
x: 0,
y: 0,
},
title: "dummy object",
status: 0,
ticks: 0,
spriteIndex: 0,
}
gameObject.SetHandler(gameObject) //!
heroObject := &HeroGameObject{
GameObject: GameObject{
Point: Point{
x: 0,
y: 0,
},
title: "hero object",
status: 0,
ticks: 0,
spriteIndex: 0,
},
health: 0,
}
heroObject.SetHandler(heroObject) //!
gameObject.Update()
heroObject.Update()
}
http://play.golang.org/p/GIwOknSSzx
Is it okay to have "gameObject.SetHandler(gameObject)"?