Reputation: 5434
I have a class which is becoming a God Object. In this game, it manages the main Game Scene itself, which should be the reason why it is becoming this large.
But there are some portions of this class that I can group together. Specifically, they deal with a special mode which is triggered randomly in the game.
I want to know what would be the best approach to separate this behavior and turn it into an Object. I'm lost here, since this is a behavior and not a "thing", so I can't think of a nice and elegant solution.
class Game
var lives = 1
var score = 0
var time = 0
doStuff() {}
doMoreStuff() {}
specialActivate() {}
specialUpdate() {}
specialInput() {}
specialDeactivate() {}
As you can see, there are many "special mode" related functions. Problem is that some of these functions rely on the variables and methods contained in Game.
Create a new class and send in the needed variables and callbacks together in a Context (or Model) object.
class Game
var lives = 1
var score = 0
var time = 0
var special = new Special(new SpecialContext(lives, score, time, doStuff))
doStuff() {}
doMoreStuff() {}
class Special
var context:SpecialContext
constructor(context:SpecialContext)
this.context = context
activate() {}
deactivate() {}
input() {}
update() {}
class SpecialContext
var lives
var score
var time
var doStuff:Callback
constructor(lives, score, time, callbackDoStuff:Callback)
this.lives = lives
this.score = score
this.time = time
this.doStuff = callbackDoStuff
Create an interface and make Game implement that interface, to protect Game.
class Game implements IGameSpecial
var lives = 1
var score = 0
var time = 0
var special = new Special(this)
doStuff() {}
doMoreStuff() {}
class Special
var game:IGameSpecial
constructor(gameSpecial:IGameSpecial)
this.game = game
activate() {}
deactivate() {}
input() {}
update() {}
interface IGameSpecial
doStuff()
getLives()
setLives()
getTime()
setTime()
getScore()
setScore()
Send directly the game class (the dirty approach).
class Game
var lives = 1
var score = 0
var time = 0
var special = new Special(this)
doStuff() {}
doMoreStuff() {}
class Special
var game:Game
constructor(gameSpecial:Game)
this.game = game
activate() {}
deactivate() {}
input() {}
update() {}
Is there an elegant way to solve this? Does this problem have a name or a pattern associated to it?
Upvotes: 0
Views: 114
Reputation: 33978
You mention a "special mode", presumably that is opposed to the "normal mode". "Mode" is (or at least can be) a type, which would suggest using the State pattern. However, it doesn't look as though you have any sort of type code in the class to tell whether these 'special' methods should be used, so I'm assuming that there is something outside the class that decides that.
I expect that you could decompose the 'special' methods into simpler methods on the Game class. This implies that you could have the "special mode" be a Decorator that is applied to the Game at appropriate times. Whether this would work depends heavily on how the Game class is used.
Upvotes: 2
Reputation: 1195
I would do this:
1) Create an interface:
interface ISpecialAction {
execute()
}
2) implement it for every special action:
class Activation implements ISpecialAction {
setLives()
setTime()
execute()
}
3) delegate in class Game to this classes
class Game {
specialActivate() {
Activation a = new Activation()
a.execute()
}
}
This decouples the special actions from the Game class, so you will not have a God class anymore in what is concerning special actions. The interface implemented by the special action classes can help for example when using a Factory or a Builder to create the special actions.
Upvotes: 1