5

I have to implement a method to save my game in such a way that I can change the storage medium with the change of only a single variable.

Ideally I'd use an interface to designate the required method signatures and implement that interface with a different concrete class for each medium. For example, one for database, one for xml, possibly one for serialized objects. How exactly I initiate the save function?

For example, if I have a Class of type Persistence called PersistToXML, which is instantiated to some variable somewhere upon launching the game, how best should I implement it so that I can save my relevant objects as needed?

I'm hesitant to use a Singleton due to all the bad reviews I read about it, and I don't really want to have to pass this object around to every class just in case I need to save something.

  • @gnat that was my question actually. I felt it was a bit lacking, and couldn't quite visualize how it would work based on the suggestions, so I thought maybe I'd ask here for a different perspective. – agent154 Dec 2 '13 at 18:44
  • 1
    You don't need a Singleton. There is nothing wrong with instantiating your concrete Persistence object during your application's bootstrapping and then passing that single instance around where it's needed. This is a form of Dependency Injection. You may want to look into the concept of IoC Containers as well. – MetaFight Dec 2 '13 at 20:40
2

I would use something like the Factory Pattern. It would return the concrete implementation of the persistence method you require.

public class Program
{
    public void SaveGame()
    {
        var gameSaveFormat = ConfigurationManager.AppSettings["gameSaveFormat"];

        var persistence = PersistenceFactory.GetSaveMethod(gameSaveFormat);
        persistence.SaveGame();
    }
}

public interface IPersistence
{
    void SaveGame();
}

public abstract class Persistence : IPersistence
{

    public abstract void SaveGame();
}

public class SaveToDatabasePersistence : Persistence
{

    public override void SaveGame()
    {
        //Implement SaveToDB
    }
}

public class SaveToXmlPersistence : Persistence
{

    public override void SaveGame()
    {
        //Implement SaveToXML File
    }
}

public static class PersistenceFactory
{
    public static IPersistence GetSaveMethod(string saveMethod)
    {
        switch (saveMethod)
        {
            case "Xml":
                return new SaveToXmlPersistence();
                break;
            case "DB":
                return new SaveToDatabasePersistence();
                break;
            default:
                throw new Exception(string.Format("Unknown Save Method. {0}", saveMethod));
        }
    }
}

The GetSaveMethod would accept a string that would define the concrete type that you wish to return.

The Persistence abstract class is optional. You should use it if you require common functionality between concrete implementations. If you choose not to use it, each concrete type should implement the interface directly.

You haven't specified what language you are using, but in .NET you can use the ConfigurationManager class to read the persistence method from a configuration file.

Lastly

I'm hesitant to use a Singleton due to all the bad reviews I read about it, and I don't really want to have to pass this object around to every class just in case I need to save something.

doesn't quite make sense. A Singleton class is called when necessary. An object being passed to every class just in case you need to use it, is certainly an incorrect implementation of that pattern.

public void SaveGame()
{
    var persitanceMethod = MySingleton.GetInstance().PersitanceMethod;

    var persistence = PersistenceFactory.GetSaveMethod(persitanceMethod);
    persistence.SaveGame();
}

The above code would be an example (from my head) of how you would call a singleton class to retrieve a property from it.

Update


public class Program
{
    private readonly IPersistence _persistence;
    public Program(IPersistence persistence)
    {
        _persistence = persistence;
    }

    public void SaveGame()
    {
         var persistenceObject = PersistenceFactory.GetSaveMethod(_persistence.GameSaveFormat);
         persistenceObject.SaveGame();
    }
  • 1
    Using a singleton here breaks Inversion of Control. There is nothing wrong with passing in the Persistance instance everywhere it's needed. This is Dependency injection. Having to inject the dependency in a bunch of places, however, is a code smell. If several classes invoke save, then your classes aren't doing just one thing. – MetaFight Dec 2 '13 at 20:37
  • @MetaFight, if you read the last paragraph of the OP carefully, it states passing a reference to the singleton object to each class that may require it. Passing a reference to a singleton is wrong. The code example that I gave refers to the correct use of the Singleton pattern. Adding on to that, DI is an an acceptable solution to the problem also. Updated answer to reflect.... – Gibson Dec 3 '13 at 9:22
  • Also, there are also many heated debates on SO discussing the merits of the Singleton pattern: stackoverflow.com/questions/228164/… & stackoverflow.com/questions/137975/… – Gibson Dec 3 '13 at 9:29
  • you are correct, sir :) I will read more closely next time! – MetaFight Dec 3 '13 at 10:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.