Hintergrund: Ich arbeite an einem relativ großen Spielprojekt, um meine OO-Fähigkeiten zu verbessern. Ich benutze SOLID-Prinzipien und suche viel (eigentlich mehr als ich es code).JavaSE: Verwenden einer Singleton/Static-Only-Klasse zum Speichern von Ressourcen? Oder was?
Problem: Ich habe mit Ressourcen gekämpft (Sprites, um genau zu sein). An der ersten Stelle habe ich eine Klasse erstellt, die die Ressourcen des Spiels lädt (basierend auf einer Zeichenfolge, die angibt, wo sich das Spritesheet in der JAR-Datei befinden würde) und global darauf zugreifen kann. Es funktionierte basierend auf statischen Variablen. Dann las ich, dass statische Variablen für OO-Designs böse sind, und ging zu Singletons. Dann las ich, dass Singletons böse sind, und seither habe ich keine andere Option gefunden. Ich verstehe, dass der globale Zustand eine Menge Abhängigkeiten erzeugt (tatsächlich habe ich es bereits mit dieser Ressourcenklasse auf meiner Haut gespürt). Aber ich finde keinen guten Weg, es zu vermeiden.
Frage: Am Ende der Frage werden Sie meine Implementierung für die Ressourcenklasse und Sprite-Klasse sehen. Jede einzelne Klasse, die eine grafische Interpretation benötigt (Mobs, der Spieler, Kacheln, Itens usw.), hängt von der Sprite-Klasse ab. Und jede Klasse kann von der Resource-Klasse (die nur zwei Ressourcen in das Sample geladen hat, aber das ist offtopisch) Zugriff darauf haben. S * o, was wäre die beste Lösung dafür? * (Ich würde es vorziehen, wenn Sie mit Konzepten antworten, anstatt mir den Code zu geben :))
OBS: Ich habe fast das gleiche Problem mit dem Halten einer Datenbank für Kacheltypen (siehe im folgenden Code). OBS2: Weder die Datenbank noch die Ressourcen ändern sich während der Laufzeit des Spiels. Sie sind "konstant" und ich würde sie nur ändern, um neue Kacheln/Ressourcen zur Kompilierzeit hinzuzufügen. OBS2: Ich habe eine Idee, die OK sein könnte, aber ich bin nicht sicher: -Eine Superklasse für Sprite/Ressourcen erstellen und dann Unterklasse für jede Art von Ressource erstellen, die ich brauche. Ich denke nicht, dass diese Lösung Kopplungsprobleme lösen wird und die Sprite-Implementierung in verschiedene Pakete aufgeteilt wird.
public final class Resources {
private static HashMap<String, Sprite> sprites = new HashMap<String, Sprite>();
static {
loadSprites(new SpriteSheet("spritesheets/spritesheettest.png"));
}
private static void loadSprites(SpriteSheet s) {
sprites.put("Grass1", s.getRawSprite(0, 0).recolor(Color.GREEN));
sprites.put("Cave1", s.getRawSprite(0, 0).recolor(Color.GRAY));
}
public static Sprite getSprite (String name) {
return sprites.get(name);
}
}
public final class Sprite {
public static final int SIDE = 32;
private static SpriteFilter spriteFilter;
private static MySpriteRotator spriteRotator;
private BufferedImage image;
static {
spriteFilter = new MySpriteFilter();
spriteRotator = new MySpriteRotator();
}
public Sprite(BufferedImage img) {
image = img;
}
public Sprite rotate (double angle, BufferedImage sprite) {
return (spriteRotator.rotate(angle, this));
}
public Sprite recolor(Color c) {
MySpriteFilter sf = new MySpriteFilter();
return (spriteFilter.recolor(c, this));
}
public void render(Graphics2D g, int x, int y) {
g.drawImage(image, x, y, null);
}
public BufferedImage getImage() {
return image;
}
}
public final class TileDataBase {
private static HashMap<Integer, Tile> database = new HashMap<Integer, Tile>();
private static HashMap<Integer, Tile> rgbDatabase = new HashMap<Integer, Tile>();
private static final Tile grass = new MyTile(1, new Color(0, 255, 0), Resources.getSprite("Grass1"));
private static final Tile cave = new AnimatedTile(2, new Color(127, 127, 127), Resources.getSprite("Cave1"), new Animator(new Sprite[] {Resources.getSprite("Grass1"), Resources.getSprite("Cave1")}));
private TileDataBase() {
}
public static Tile getTileByID(int id, int x, int y) {
Tile t = database.get(id).cloneTile();
if (t == null) {
try {
throw new Exception("No tile for such id");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
t.setX(x);
t.setY(y);
return t;
}
static Tile getTileByRGB(int rgb, int x, int y) {
Tile t = rgbDatabase.get(rgb).cloneTile();
if (t == null) {
try {
throw new Exception("No tile for such rgb");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
t.setX(x * Sprite.SIDE);
t.setY(y * Sprite.SIDE);
return t;
}
static void putToDatabase(int id, Tile tile) {
database.put(id, tile);
}
static void putToRGBDatabase (Color c, Tile t) {
rgbDatabase.put(c.getRGB(), t);
}
}
Hat eine dieser Antworten Ihnen geholfen? –