![](/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.