2015-04-30 135 views
3

最近我一直在閱讀很多關於使用static的文章。我讀了很多關於被濫用的static。我要確保我正確地使用它在這Manager類:我是否正確使用靜態?

public class SignManager 
{ 
    private static HashMap<String, List<GameSign>> signsBySection = new HashMap<>(); 
    private static HashMap<String, List<GameServer>> serversBySection = new HashMap<>(); 
    private static HashMap<String, GameServer>serverNames = new HashMap<>(); 
    private static HashMap<Sign, GameSign> gameSignBySign = new HashMap<>(); 
    private static List<GameServer> availableServers = new ArrayList<>(); 
    private static List<GameServer> displayedServers = new ArrayList<>(); 

    public static void addSign(String section, Sign sign) 
    { 
     List<GameSign> signs = signsBySection.get(section); 

     if(signs == null) 
      signsBySection.put(section, signs = new ArrayList<>()); 

     GameSign gameSign = new GameSign(section, sign.getLocation()); 

     signs.add(gameSign); 
     gameSignBySign.put(sign, gameSign); 
    } 

    public static void addServers(String section, List<String> range) 
    { 
     List<GameServer> servers = SignManager.serversBySection.get(section); 

     if(servers == null) 
      SignManager.serversBySection.put(section, servers = new ArrayList<>()); 

     for(String s : range) 
     { 
      GameServer server = new GameServer(s); 

      servers.add(server); 
      serverNames.put(s, server); 
     } 
    } 

    public static void setAvailable(GameServer server) 
    { 
     availableServers.add(server); 
    } 

    public static void replaceDisplayed(GameServer old, GameServer newServer) 
    { 
     removeDisplayed(old); 
     displayedServers.add(newServer); 
    } 

    public static void removeDisplayed(GameServer server) 
    { 
     displayedServers.remove(server); 

     if(server != null) 
      server.setSign(null); 
    } 

    public static boolean isDisplayed(GameServer server) 
    { 
     return displayedServers.contains(server); 
    } 

    public static boolean isAvailable(GameServer server) 
    { 
     return availableServers.contains(server); 
    } 

    public static void tick() 
    { 
     for(GameSign sign : getAllGameSigns()) 
      sign.tick(); 

     GameSign.addDot(); 
    } 

    public static GameServer getGameServer(String name) 
    { 
     return serverNames.get(name); 
    } 

    public static GameServer getNextAvailableServer() 
    { 
     if(availableServers.size() == 0) 
      return null; 

     GameServer server = availableServers.get(0); 
     availableServers.remove(0); 
     return server; 
    } 

    public static GameSign getGameSign(Sign sign) 
    { 
     return gameSignBySign.get(sign); 
    } 

    public static Set<Map.Entry<String, List<GameSign>>> getSignsBySection() 
    { 
     return signsBySection.entrySet(); 
    } 

    public static Collection<GameServer> getAllServers() 
    { 
     return serverNames.values(); 
    } 

    public static Collection<GameSign> getAllGameSigns() 
    { 
     return gameSignBySign.values(); 
    } 
} 

我也看了,如果類有一個狀態,它不應該是static。因此,使用static地圖意味着班級有一個州,我在這裏正確使用static

在此先感謝。

+4

爲什麼是這一切的靜態呢?爲什麼不把他們全部*實例*變量和*實例*方法,並確保你需要一個'SignManager',你有一個合適的實例?不可思議的是,會有兩個不同的'SignManager'實例與不同的服務器等? (尤其是,它使測試更容易...) –

+0

只需要一個SignManager,因爲所有的GameSigns都保存在一起。 – XLordalX

+3

但是,爲什麼不只是創建一個'SignManager'的實例*,它可以提供給需要它的一切?再次,這將使測試更容易 - 以及未來擴展到一個後來的系統,他們*不*所有保存在一起... –

回答

1

面對它,我會說你是而不是正確使用靜態。該類維護受addServers和addSign方法影響的狀態。該狀態是靜態維護的,這意味着如果您有兩個不同的SignManager對象實例,則它們將共享相同的狀態。這可能是你想要的 - 它可能不是。

如果它你想要什麼,那麼使用Singleton模式提供了一個更常見的方法來實現這一點。如果它不是你想要的,那麼你應該考慮將靜態變量改爲實例變量(並且對方法簽名進行相應的更改)

1

如果您按照上述方法制作了所有的static,它將使您的代碼更加完善緊密耦合。您可以刪除該類中的所有關鍵字,並在其他組件中使用它的實例,並且代碼仍然是正確的。

現在,如果您希望對您的類進行不同的實現(或者出於某種原因有多個實例),則不必更改那麼多,只需將該類的新實現注入到使用它的組件。

爲不使用static調用的類編寫單元測試也更容易。

這篇文章可能有助於揭示爲什麼它是最好的,以避免他們更多的光... http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container