Como posso implementar uma função modular de “salvar” para um jogo?

5

Eu tenho que implementar um método para salvar meu jogo de tal forma que eu possa mudar o meio de armazenamento com a mudança de apenas uma única variável.

O ideal seria usar uma interface para designar as assinaturas de método necessárias e implementar essa interface com uma classe concreta diferente para cada meio. Por exemplo, um para banco de dados, um para xml, possivelmente um para objetos serializados. Como exatamente inicio a função salvar?

Por exemplo, se eu tenho uma classe do tipo Persistence chamada PersistToXML, que é instanciada para alguma variável em algum lugar ao iniciar o jogo, como devo implementá-la para que eu possa salvar meus objetos relevantes conforme necessário?

Eu hesito em usar um Singleton devido a todos os comentários ruins que eu li sobre ele, e eu realmente não quero ter que passar este objeto para todas as classes apenas no caso de eu precisar salvar algo.

    
por agent154 02.12.2013 / 18:24
fonte

1 resposta

2

Eu usaria algo como o padrão de fábrica . Ele retornaria a implementação concreta do método de persistência que você exige.

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));
        }
    }
}

O GetSaveMethod aceitaria uma string que definiria o tipo concreto que você deseja retornar.

A classe abstrata Persistência é opcional. Você deve usá-lo se precisar de funcionalidade comum entre implementações concretas. Se você optar por não usá-lo, cada tipo de concreto deve implementar a interface diretamente.

Você não especificou o idioma que está usando, mas no .NET você pode usar o ConfigurationManager para ler o método de persistência de um arquivo de configuração.

Por último

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.

não faz muito sentido. Uma classe Singleton é chamada quando necessário. Um objeto sendo passado para todas as classes apenas no caso de você precisar usá-lo, é certamente uma implementação incorreta desse padrão.

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

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

O código acima seria um exemplo (da minha cabeça) de como você chamaria uma classe singleton para recuperar uma propriedade dele.

Atualizar

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

    public void SaveGame()
    {
         var persistenceObject = PersistenceFactory.GetSaveMethod(_persistence.GameSaveFormat);
         persistenceObject.SaveGame();
    }
    
por 02.12.2013 / 18:43
fonte