繁体   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