2015-04-30 138 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