In a 2D game, buildings can be upgraded with modules; Those modules can be bought in a shop.

The shop is represented by a stereotyped grid of icons, each icon representing a buyable module. When the mouse hovers an icon, the name a description of the associated module appear in a popup.

Currently, the modules are model objects extending an abstract Module class wearing the following data:

  • The name of the module
  • A description of what it does to your building
  • The icon used to display the module in the shop's grid
  • Also, some f(building)-like methods to actually "modulize" the building...

At the beginning of the game, the shop is provided with a list of modules. When applying a module to a building the f(building) methods are called on the bought module. Thus, even not using the Singleton pattern, each *Module class is instantiated only once.

I'm conscious that this design is not really optimal:

  • First, a module, a model object, embeds its own icon, a view representation.
  • And more important: a module is stateless because the same object can be applied on several buildings (possibly of different players); in order to be stateful, a module would have to wear a [building] => data map... I don't know why, but I have a bad feeling about this solution...

Question time:

  • Is the [building] => data map effectively a bad solution?
  • If so, what's the best way to solve the "statefulness" pitfall I'm encountering?
  • Subsidiary one: also, it would be more MVC-compliant if each model object didn't have to wear an image...
  • Feel free to correct any language mistake of mine. BTW, it's my first post here, so I'm not sure of the tags I used; feel free to change them as well.
    – user276191
    Commented Aug 7, 2017 at 9:44
  • 1
    If I buy an upgrade to a building, can I choose which of my possibly several buildings to apply it to? Can I choose in which order to apply multiple upgrades or does that not make any sense? Can I buy an upgrade multiple times? Commented Aug 7, 2017 at 9:54
  • Yes: you can choose which building (one at a time) you want to upgrade. -- The effects of a newly applied module are stacked on top of the effects already set up by other modules; there's an order, but you don't chose it... -- There's no limit on the number of modules you can apply to a building (maybe in the future), and you can stack the same module on one building several times.
    – user276191
    Commented Aug 7, 2017 at 10:06

1 Answer 1



First, you have IModuleDefinition interface. Primary purpose of this interface is to identify a module, possibly through having some unique identifier for a module. It will have methods like CreateView and CreateModule. Those will create concrete instances that will be used to display the module information (IModuleView) and implement the module behavior (IModule). This also means any number of instances can be created for each type of module, so state can be inside the module instance.

  • If I understand well, the IModuleDefinition is a IModuleView - IModule couple... Where would all these classes and interfaces be located (namespacingly speaking)?
    – user276191
    Commented Aug 7, 2017 at 18:13
  • @Odepax No definition is not a view/module. It creates them. And namespace-wise, they would all be in same place. I can even imagine ConcreteModuleDefinition class with ConcreteModuleView and ConcreteModule being private classes of it.
    – Euphoric
    Commented Aug 7, 2017 at 18:59
  • So they are in the same namespace, but is this one of the MVC namespaces or a new one? How do I extend ConcreteModuleView and ConcreteModule if they are private?
    – user276191
    Commented Aug 8, 2017 at 7:01
  • Wait a minute... What's the purpose of separating the view and the behavior if "they would all be in same place" eventually? BTW: in your design, is an IModuleView implementation just an object that wears an image or a URI to it, or barely a custom UI control?
    – user276191
    Commented Aug 9, 2017 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.