2014-11-05 56 views
1

想象一下你正在做的是使用一些紋理遊戲對象:如果null傳遞如何使用繼承緩存類的靜態數據?

public class Action { 
    //This two can (must) be overriden 
    public const string _HoverCursor = "Textures/cursors/select"; 
    public virtual string HoverCursor { get { return _HoverCursor; } } 

    //This is the get texture by string 
    private static Texture2D cursorTex = null; 
    public static Texture2D cursor { get { return ResourceManager.loadTexture(ref cursorTex, HoverCursor); } } 
} 

loadTexture功能將加載質感。否則,它只是返回原始值。

正如你所看到的,我正在製作一個Action原型。會出現類似的攻擊,移動Build。我想爲每個類定義存儲一個(和不同的)紋理對象。這個對象應該是lazy-loaded when needed使用上面的getter。

由於static property can't be overriden,我怎麼能實現這個所有的兒童實例?

這裏的loadTexture

public static Texture2D loadTexture(ref Texture2D target, string name) 
    { 
     if (target == null) 
     { 
      target = (Texture2D)Resources.Load(name, typeof(Texture2D)); 
     } 
     return target; 
    } 

回答

1

您可以使用繼承和多態與實例成員,並使用一個靜態工廠方法作爲幌子,簡化了執行的實例。

例如

public abstract class Action 
{ 
    public abstract void LoadTexture(...); 
} 

// Since static façade class has a generic type parameter, we're talking 
// about a completely different class than just "Action" and both can co-exist! 
public static class Action<TAction> where TAction : Action, new() 
{ 
    public static Texture2D LoadTexture(...) 
    { 
     // Since generic TAction parameter must implement a public parameterless 
     // constructor, you may instantiate T like a concrete class: 
     return new TAction().LoadTexture(...); 
    } 
} 

因此,你可以按如下方式使用靜態方法:

Texture2D texture = Action<CustomAction>.LoadTexture2D(...); 
+0

這真的很酷,但它有效嗎?我希望數據是靜態的,以節省RAM,但CPU更重要,尤其是這些日子裏所有這些8GB RAM ...... – 2014-11-12 17:12:54

+0

@TomášZato是啊...嗯,我想你會加載紋理或任何東西,你應該卸載他們,如果你不需要他們在某些情況下。順便說一句,看看'懶惰' – 2014-11-12 23:31:42

+0

有趣。不知道「懶惰」,我寫了一個'LazyResource 'class ... – 2014-11-13 00:08:41

1

你幾乎已經自己回答了這個問題:

由於靜態屬性不能被覆蓋,我怎麼能實現這個所有的兒童實例?

只需將該屬性設爲實例屬性即可。例如:

public class Action { 
    //This two can (must) be overriden 
    public const string _HoverCursor = "Textures/cursors/select"; 
    public virtual string HoverCursor { get { return _HoverCursor; } } 

    //This is the get texture by string 
    private static Texture2D cursorTex = null; 
    public virtual Texture2D cursor 
    { 
     get 
     { 
      return ResourceManager.loadTexture(ref cursorTex, HoverCursor); 
     } 
    } 
} 

public class Attack { 
    //This two can (must) be overriden 
    public const string _HoverCursor = "Textures/cursors/attack"; 
    public virtual string HoverCursor { get { return _HoverCursor; } } 

    //This is the get texture by string 
    private static Texture2D cursorTex = null; 
    public override Texture2D cursor 
    { 
     get 
     { 
      return ResourceManager.loadTexture(ref cursorTex, HoverCursor); 
     } 
    } 
} 

你仍然會保存每一類中添加質感,但由於每個類的實例,你就可以獲取正確的遊標紋理該類。大概你只需要在無論如何都有類的實例時設置光標,所以這不應該是一個不合理的限制。在上述

需要注意的是,如果沒有其他的代碼確實需要HoverCursor屬性,你可以擺脫它,使_HoverCursor常量的私有成員,然後使用直接在cursor屬性的getter。

另請注意,此實現不是線程安全的。只要你總是從一個線程訪問cursor屬性,沒關係。但是,如果不是(或者僅僅爲了簡單),您可能更喜歡使用Lazy<T>類。例如:

//This is the get texture by string 
    private static Lazy<Texture2D> cursorTex = 
     new Lazy<Texture2D>(() => ResourceManager.loadTexture(HoverCursor)); 
    public virtual Texture2D cursor 
    { 
     get 
     { 
      return cursorTex.Value; 
     } 
    } 

在這個版本中,注意loadTexture()方法已經改變總是加載紋理,因而不需要ref參數。 Lazy<T>類將確保線程安全的延遲初始化,每個類僅調用loadTexture()一次。