簡體   English   中英

JavaSE:使用singleton / static-only類來保存資源? 要不然是啥?

[英]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);

}

}

您是否考慮過使用像springguice這樣的依賴注入框架? 它可以將資源訪問器類注入到使用它的所有位置。 在引擎蓋下,資源類可以表現得像一個單獨的實際資源數據被緩存左右。 但你不會遭受單身人士或全球國家的“邪惡”。 您可以將資源類定義為接口,並在單元測試中輕松模擬它。

快速回答而不必深入研究這個問題的細節......你可以使用Guava Supplier界面 ,特別是你可以使用Suppliers.ofInstance(T t 這可能比Guice更輕巧。

普通的vanilla javase解決方案是傳遞對Resources類的引用。 通常,您的類將分為兩類中的一類:更大和更少的實例,更小和更多實例。 對於前者,您通常使用對Resources類的引用來實例化它們(或者,該類可能已經引用了另一個引用Resources類的類)。 對於后者,您通常會將Resources類添加為可能需要它的方法的參數(這允許類很小並且沒有很多額外的引用)。

另外,我假設您將設置您的Resources類,因此它具有所有資源的句柄(例如,您可以從中獲取精靈和圖塊)。

最后,您將在程序的入口點(例如main方法)實例化您的Resources類,並將其傳遞給創建的其他頂級對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM