[英]best practice to avoid static fields
我已经阅读了一些有关静态变量的缺点的问题(例如, 为什么静态变量被认为是邪恶的 ,但我发现在选择最佳解决方案以避免使用它们时遇到了一些困难。
例如,在我的简单国际象棋应用程序中,我有一个抽象类Piece,其中包含许多子类。 每个片断都必须有一个BufferedImage变量image ,但是我想为每个片断仅加载一次图像 。
通过使用静态变量,这将非常容易:
abstract class Piece
{
// ...
public abstract BufferedImage getImage();
}
class Bishop extends Piece
{
private static final BufferedImage image = null;
static{
try{
image = ImageIO.read(ClassLoader.getSystemResource("chess/img/pieces/Bishop.png"));
}
catch(IOException ex){
// ...
}
}
public BufferedImage getImage(){
return image;
}
}
当然,此代码不遵循OOP,并且继承不用于image变量。
一种解决方案是将所有图像加载到外部类中,并让所有子类实例保持对同一对象的引用:
abstract class Piece
{
final BufferedImage image;
public Piece(/* ... */ BufferedImage image){
this.image = image;
}
public BufferedImage getImage(){
return image;
}
}
class Bishop extends Piece
{
public Bishop(/* ... */ BufferedImage image){
super(/* ... */ image);
// ...
}
}
但是,如果我需要从n个不同的类中创建子类实例,该怎么办? 假设我仅创建这n个类的一个实例,则图像将至少加载n次。
我已经考虑过将图像引用保留在Singleton模式设计的类中,但我也想将图像变量保留在Piece类中,以便对每个Piece都简单地使用getImage()方法。
将第二种解决方案与Singleton模式结合使用是否是一个好的设计,因此我会将对通过SingletonClass.getXxxImage()方法获得的相同BufferedImage的引用传递给每个Piece的子类构造函数?
还是有更好的方法? 当然,多次加载BufferedImage并不是很邪恶,但是我想有一个通用的解决方案来避免代码的无用重复。
谢谢你的帮助 !
在某些情况下, static
是必经之路。 但是通常,对静态内容的需求表明OO设计存在缺陷。
在您的特定情况下,我认为您缺少对PieceType
的抽象。 如果将每个样件类型建模为一个类,则将实例化拼接的需求与某种特殊样件的一般描述混合在一起。
即,您的两个主教需要共享不特定于白色或黑色主教的数据(图像)和行为(移动模式),但通常对于主教来说是共享的。
尽管共享的行为非常适合作为方法定义的类(将由所有实例共享),但是共享的数据将需要是static
或为每个实例冗余地复制。
这里可能缺少的是一些PieceType
抽象,它封装了PieceType
的数据和行为。
可以将其建模为一个枚举(因为您有固定数量的类型),将每种类型的零件作为实例列出:
enum PieceType {
BISHOP {
@Override public void move() { /* whatever */ }
},
PEON {
...
}
private final BufferedImage image;
PieceType() {
image = ImageIO.read(ClassLoader.getSystemResource("chess/img/" + name().toLowerCase() + ".png"));
}
public abstract void move(); // or whatever
}
现在,您只需要一个Piece
类型,它将所有与类型相关的东西委派给它的PieceType:
class Piece {
private final PieceType pieceType;
// position and all...
Piece(PieceType pieceType) {
this.pieceType = pieceType;
}
// behavior that delegates to the pieceType whenever necessary
}
请注意,上面定义的enum
会固有地创建static
变量(其常量)。 但这是static
的可接受/鼓励的用法之一(正如我在简介中所提到的)。
注意, static
变量本身并不坏。 他们只会被不了解OOP的新程序员过度使用。 实际上,这种情况似乎是对static
字段的合理使用。 每个Bishop
都有完全相同的视觉效果,因此多次加载相同的图像似乎很浪费。
另一方面,将图像传递给构造函数更灵活。 它将图像加载的责任留给了其他人。 它还使您可以更轻松地更改使用的图像。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.