[英]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.