0

I'm making a game for a class project, and the professor said that he wanted us to implement some form of functionality to save the game state, and that I should be able to plug in any "type" of saving as desired -- be it using serialized objects, xml, database, etc... It was suggested to have a master interface and have several implementing classes that save using their respective method... but I'm not sure how to actually approach this.

For one, I'm confused about which classes will implement this interface. Will it be all my objects? Or will it be the classes whose job it is to save the data? Should each object be responsible for saving its own data, or will one master class be responsible for saving the data of all objects? Should I probably use an abstract class instead? Also, it seems to me that each of my objects will have to implement Serializable just in case such a method is used, even if it won't be...

I don't need help with code so much as I need help understanding the structure of this setup that will work best. I need to make sure everything is as modular as possible, as this is a project where I have to apply the many principles of software engineering to make "great software"...

Mirrana
  • 1,601
  • 6
  • 28
  • 66
  • 1
    You will need to store all information that makes the current state of the program unique. If you are using the MVC architecture, then this would the Model. – vandale Nov 21 '13 at 19:46
  • @vandale I'm not confused as to WHAT I need to save, but how to implement the saving code so that I can change my mind at any time about what medium I want it saved to. – Mirrana Nov 21 '13 at 19:48
  • The interface you are looking for is `Externalizable`. – AJMansfield Nov 21 '13 at 20:32

2 Answers2

1

The interface you are thinking of already exists: java.io.Externalizable

This interface extends Serializable to allow the implementer to have control over the format used to store the object.

However, Serializable is probably good enough for you; just mark the fields that don't need to be saved transient.

AJMansfield
  • 4,039
  • 3
  • 29
  • 50
  • Although `Serializable` may be 'good enough' for my project, it's not what the prof wants. He wants it such that the storage medium can be changed with minimal change in code. – Mirrana Nov 22 '13 at 01:19
  • @agent154 You change the 'storage medium' by changing what `ObjectOutputStream` you serialize your objects into, not by changing the implementation of the serialization process. – AJMansfield Nov 22 '13 at 01:23
0

You should have a look at different design patterns that help you to fulfill your requirements.

The memento pattern for example provides the ability to save an object and restore its previous state. If you modify it slightly, it may fit to your needs:

public interface Saveable {
    void save(Memento memento);
    void restore(Memento memento);
}

public interface Memento {
    void putString(String key, String value);
    String getString(String key);
    void putInteger(String key, int value);
    int getInteger(String key);
    // ... put/get for other data types
    Memento getChild(String key, boolean createIfNotExisting);
}

All your game parts that have something to save should implement Saveable. When save or restore is called, they write/read their internal representation to/from an external state object called Memento.

By having different implementations of Memento you can realize your storage via XML files, object serialization or even relational databases (XMLMemento, SerializationMemento, JPAMemento, ...). At runtime, the concrete implementation is chosen by an abstract factory or factory method.

Usage sample:

Memento memento = mementoFactory.create();
player.save(memento.createChild("player", true));
board.save(memento.createChild("board", true));
...
memento.store();

For example the Eclipse framwork uses this pattern to save the state of UI parts. (But the only implementation it offers is XMLMemento).

Another useful pattern is the builder pattern. Its intent is to separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations. The english wiki page misses some important aspects of this pattern, so if it fits your needs you should really read the original chapter in the book.

Sample usage for kind of builder:

GameStateSaver saver = saverFactory.createSaver();
saver.savePlayer(player);
saver.saveBoard(board);
...
saver.store();

Here, the game objects themselves don't know that/how they are saved, but instead the GameStateSaver implements that knowledge. Note that this has also a disadvantage: The objects must offer all their state via public API (so internal, private state cannot be saved because it's not accessible by the saver).

isnot2bad
  • 24,105
  • 2
  • 29
  • 50
  • Would I have to have a different Memento class for each type of object that I wish to save? It seems to me like the available data types will have to match up between the originator and the caretaker for this to work... so if I have an object for player, I'd need a PlayerMemento so it knows how to handle the relevant information specific to Player, and similarly for "Board" if I want to save the state of the game board. – Mirrana Nov 22 '13 at 01:17
  • No, the memento interface abstracts from the concrete persistence strategy, so you will have one implementation per data store. – isnot2bad Nov 22 '13 at 06:56