![](/img/trans.png)
[英]What is difference between using singleton class and class with static methods?
[英]JavaSE: Using a singleton/static-only class to hold resources? Or what?
背景 :我正在開展一個相當大的游戲項目,以提高我的OO技能。 我一直在使用SOLID原則並進行大量搜索(實際上比我的代碼更多)。
問題 :我一直在努力尋找資源(精靈,具體而言)。 在fisrt的地方,我創建了一個類,它將在游戲中加載資源(基於指定spritesheet在jar文件中的位置的字符串)並提供對它的全局訪問。 它基於靜態變量工作。 然后我讀到靜態變量對OO設計是邪惡的,並且去了單身人士。 然后,我讀到單身人士是邪惡的,因為我沒有找到任何其他選擇。 我知道全局狀態會產生很多依賴關系(事實上,我已經在這個資源類的皮膚上感覺到了它)。 但我沒有找到任何避免使用它的好方法。
問題 :在問題的底部,您將看到我對資源類和精靈類的實現。 每個需要的類都有圖形解釋(怪物,玩家,瓦片,itens等)取決於Sprite類。 每個類都可以通過Resource類訪問它(它只在示例中加載了兩個資源,但那是offtopic)。 S * o,對此最好的解決方案是什么? *(我希望你回答概念,而不是給我完成的代碼:))
OBS:我對於為磁貼類型保存數據庫幾乎有同樣的問題(參見下面的代碼)。 OBS2:在游戲運行時期間,數據庫和資源都不會改變。 它們是“常量”,我只會更改它們以在編譯時添加新的tile /資源。 OBS2:我有一個可能沒問題的想法,但我不確定: - 為sprite / resources創建一個超類,然后為我需要的每種類型的資源創建子類。 我認為這個解決方案不會解決耦合問題,它會將精靈實現分成不同的包。
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);
}
}
快速回答而不必深入研究這個問題的細節......你可以使用Guava Supplier界面 ,特別是你可以使用Suppliers.ofInstance(T t
) 。 這可能比Guice更輕巧。
普通的vanilla javase解決方案是傳遞對Resources類的引用。 通常,您的類將分為兩類中的一類:更大和更少的實例,更小和更多實例。 對於前者,您通常使用對Resources類的引用來實例化它們(或者,該類可能已經引用了另一個引用Resources類的類)。 對於后者,您通常會將Resources類添加為可能需要它的方法的參數(這允許類很小並且沒有很多額外的引用)。
另外,我假設您將設置您的Resources類,因此它具有所有資源的句柄(例如,您可以從中獲取精靈和圖塊)。
最后,您將在程序的入口點(例如main方法)實例化您的Resources類,並將其傳遞給創建的其他頂級對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.