Рекомендуется ли иметь статическую переменную, которая поддерживает состояние? - PullRequest
1 голос
/ 13 декабря 2010

У меня есть метод утилиты шифрования, который опирается на внешнюю зависимость - ключ шифра, который извлекается из файла свойств.Он может быть извлечен из текущей базы кода, которую я унаследовал, так как он основан на создании новых объектов, чтобы иметь возможность получить значение свойства в файле свойств.Например, если вы хотите получить ключ шифрования из файла свойств, он будет выглядеть следующим образом:

    public synchronized static String encrypt(String someTextToEncrypt) {
             String propertyValue = null;
             propertyValue = getProcessCommonBase().
                                getProcessProperties.getProperty("CIPHER_KEY");
                     /*encrypt algorithm*/
             return encryptedForm;
        } 
    private synchronized static ProcessCommonBase getProcessCommonBase() {
            if (processCommonBase == null) {
                 processCommonBase = new ProcessCommonBase();
            }
            return processCommonBase;
    }
    private static ProcessCommonBase processCommonBase;

EDITED: При разработке используется нечто вроде переменной экземпляра processCommonBaseхорошая практика, чтобы сделать?Насколько я понимаю, хорошей практикой является то, что статические переменные должны быть окончательными и не изменяться.В этом случае, однако, класс ProcessCommonBase поддерживает состояние и может быть изменен.

НОВЫЙ ВОПРОС: Если статический метод полагается на что-то внешнее, я не должен просто пометить методБазовая переменная processCommon не статична, а в Spring просто создайте для нее определение компонента?Что лучше?

Ответы [ 3 ]

1 голос
/ 13 декабря 2010

Я согласен с Joonas. Я не понимаю, почему бы не сделать переменную окончательной. Не могли бы вы уточнить, что именно вы подразумеваете под этим:

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

Даже если переменная является конечной, вы все равно можете изменить объект, на который она ссылается, точно так же, как вы делали бы это с неконечной переменной. Вот почему для статического метода вполне нормально иметь статическую переменную, поддерживающую его состояние, но ничто не мешает вам сделать ее окончательной в этом случае. Почему бы не сделать это:

private static ProcessCommonBase processCommonBase = new ProcessCommonBase();

Возможно, что-то мешает вам создать processCommonBase во время статической инициализации, но это не очевидно из предоставленной вами информации.

1 голос
/ 13 декабря 2010

Кто-то уже прокомментировал ваш конкретный случай, но в целом то, что вы описали, это эффективная конечная статическая переменная, которая просто создается "лениво" (то есть, только при необходимости). Это хороший подход, если создание экземпляра ProcessCommonBase является дорогим и редким событием, хотя вы должны быть осторожны, чтобы получить к нему доступ только через метод getter. С другой стороны, если ProcessCommonBase будет создаваться всякий раз, когда используется окружающий класс, то сделать его на самом деле окончательным является лучшим подходом: он проще (менее подвержен ошибкам, так как вам не нужно не забывать использовать метод getter исключительно), и на самом деле будет немного дешевле, так как конечная переменная инициализируется только при первом использовании окружающего класса, и вам не нужна (синхронизированная!) нулевая проверка каждый раз при доступе к нему (конечно, если вы используйте> 1 потоков и ProcessCommonBase не является потокобезопасным, тогда вам нужно где-то синхронизироваться).

Ответ на второй вопрос: быть статичным или нет и полагаться на некоторые внешние свойства системы - это две разные вещи. Я не знаю, что делает Spring, но если ваш метод по сути является функцией - «value in, result out» - то это статический метод по своей природе, даже если он считывает свою конфигурацию из какого-то системного свойства. Делать такие методы экземплярами методов можно, но если это только усложняет вещи и ничего не дает, зачем беспокоиться?

0 голосов
/ 13 декабря 2010

Использование статики часто осуждается с точки зрения проектирования ОО, поскольку оно обеспечивает тесную связь между объектами. С помощью статических методов невозможно отделить интерфейс от его фактической реализации. Такое отсутствие развязки может, например, стать проблемой, если вы хотите выполнить модульное тестирование одного класса, поскольку его нельзя отделить от других статических частей.

В современном Java-ландшафте ваш класс синглтон-крипт может быть намного лучше спроектирован с помощью Dependency Injection (DI). ProcessCommonBase также может быть реализован как синглтон DI, если у него не было такого сильного запаха кода, потому что если это god-object , то его следует рефакторинг, например, с помощью DI для ввода свойств ты склепа класс.

Пример кода на основе Google Guice:

@Singleton
public MyCrypt {
  private final key;

  @Inject
  MyCrypt(@CipherKey String key) {
    this.pBase = pBase;
  }

  public synchronized String encrypt(String someTextToEncrypt) { 
    /*encrypt algorithm*/ 
    return encryptedForm; 
  }  
}

Настройка свойств DI:

public class PropertiesModule extends AbstractModule {

  @Override
  protected void configure() {
    String key = .. what ever ..
    bind(String.class).annotatedWith(CiperKey.class).toInstance(key);
  }

Дополнительные примеры DI можно найти здесь: http://java.dzone.com/articles/cdi-overview-part-1

Populair Java DI реализации: Guice , Spring и Java EE6 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...