2015-04-30 8 views
3

В последнее время я читал много сообщений об использовании static. Я много читал о злоупотреблении static. Я хочу быть уверен, что я использую его правильно в этом классе менеджер:Я использую статические правильно?

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 Maps означает, что у класса есть состояние, и правильно ли я использую static?

Заранее спасибо.

+4

Почему все это статические вообще? Почему бы просто не сделать их всеми * экземплярами * переменных и * экземплярами * методов и убедиться, что там, где вам нужен 'SignManager', у вас есть соответствующий экземпляр? Немыслимо ли, что существуют два разных экземпляра «SignManager» с разными серверами и т. Д.? (В частности, это намного проще проверить таким образом ...) –

+0

Существует только один SignManager, потому что все игры GameSign сохраняются вместе. – XLordalX

+3

Но почему бы просто не создать один экземпляр 'SignManager', который вы предоставите всему, что в нем нуждается? Опять же, это облегчит тестирование, а также последующее расширение до более поздней системы, в которой они не будут сохраняться вместе ... –

ответ

1

С первого взгляда, я бы сказал, что вы не с использованием статических правильно. Класс поддерживает состояние, на которое влияют методы addServers и addSign. Состояние поддерживается статически, что означает, что если бы у вас был два отдельных экземпляра объекта SignManager, оба будут иметь одно и то же состояние. Это может быть то, что вы хотите - возможно, это не так.

Если является, что вы хотите, то использование шаблона Singleton обеспечивает более обычный способ достижения этого. Если это не то, что вы хотите, то вам следует рассмотреть возможность изменения статической переменной на переменные экземпляра (и внесение соответствующих изменений в сигнатуры метода)

1

Если вы сделаете все static, как вы уже выше, это сделает код более тесно связаны. Вы можете удалить все ключевые слова static из этого класса и использовать его в других компонентах, и ваш код будет по-прежнему верным.

Теперь, если вы хотите сделать другую реализацию своего класса (или по какой-то причине несколько экземпляров), вам не нужно так сильно изменять, просто вставьте новую реализацию класса в компоненты, которые его используют.

Также легче написать модульные тесты для классов, которые не используют вызовы static.

Эта статья может помочь пролить свет на то, почему это лучше, чтобы избежать их ... http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container

Смежные вопросы