douyou4819 2014-12-16 13:09
浏览 24
已采纳

消除方法重复

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)"?

  • 写回答

1条回答 默认 最新

  • doufen5175 2014-12-16 13:23
    关注

    How about using flag function and base interface, like this?

    type BaseGameObject interface {
        Ticks() int
        IncSpriteIndex()
        AfterUpdate()
    }
    
    func UpdateGameObject(o BaseGameObject) {
        if o.Ticks() == 0 {
            o.IncSpriteIndex()
            o.AfterUpdate()
        }
    }
    
    func (o *GameObject) Ticks() int {
        return o.ticks
    }
    
    func (o *GameObject) IncSpriteIndex() {
        o.spriteIndex++
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改