Существует ли обычно используемый шаблон OO для хранения «постоянных переменных»? - PullRequest
2 голосов
/ 09 февраля 2009

Я работаю над небольшим проектом игры в пинбол для хобби и ищу шаблон для инкапсуляции постоянных переменных.

У меня есть модель, в которой есть значения, которые будут постоянными в течение срока службы этой модели, например. максимальная скорость / максимальная сила тяжести и т. д. Во всех графических интерфейсах и других областях эти значения необходимы для правильной проверки ввода. В настоящее время они включены либо как ссылки на public static final, либо просто жестко запрограммированы. Я хотел бы инкапсулировать эти «постоянные переменные» в объект, который может быть введен в модель и получен с помощью view / controller.

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

Я ищу способ достичь этого, который:

  • имеет безопасность типов времени компиляции (т.е. не отображает строку в переменную во время выполнения)
  • избегает чего-либо статического (включая перечисления, которые не могут быть расширены)

Я знаю, что мог бы определить интерфейс, который имеет такие методы, как:

 public int getMaximumSpeed();
 public int getMaximumGravity();

... и внедрить экземпляр этого в модель и каким-то образом сделать его доступным. Однако это приводит к большому количеству шаблонного кода, который довольно утомительно писать / тестировать и т. Д. (Я делаю это для забавы: -)).

Я ищу лучший способ сделать это, предпочтительно тот, который имеет преимущества от того, чтобы быть частью общего словаря, как с шаблонами проектирования.

Есть ли лучший способ сделать это?

P.S. Я подумал еще немного об этом, и лучший компромисс, который я мог бы найти, это иметь что-то вроде:

public class Variables {
   enum Variable {
       MaxSpeed(100),
       MaxGravity(10)

       Variable(Object variableValue) {
          // assign value to field, provide getter etc.
       }
   }

   public Object getVariable(Variable v) { // look up enum and get member }

} // end of MyVariables

Тогда я мог бы сделать что-то вроде:

Model m = new Model(new Variables());

Преимущества : поиск переменной защищен необходимостью быть членом перечисления для компиляции, переменные могут быть добавлены с небольшим дополнительным кодом
Недостатки : перечисления не могут быть расширены, хрупкость (необходима перекомпиляция для добавления переменной), значения переменных должны быть преобразованы из Object (в Integer в этом примере), что опять-таки не является безопасным для типа хотя дженерики могут быть вариантом для этого ... как-то

Ответы [ 4 ]

2 голосов
/ 09 февраля 2009

Вы ищете Singleton или, в качестве варианта, Monostate ? Если нет, то как этот шаблон не соответствует вашим потребностям?

Конечно, вот обязательный отказ от ответственности, что Все, что угодно, это зло .

ОБНОВЛЕНИЕ: Я немного посмотрел, потому что у меня были похожие дискуссии / проблемы. Я наткнулся на список «альтернатив» классическим глобальным решениям. Мысль, которой я поделюсь.

1 голос
/ 10 февраля 2009

Спасибо за все потраченное вами время, ребята, пытающиеся разобраться в довольно странном вопросе.

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

Если кому-то интересно, я пришел к выводу, что интерфейс, обеспечивающий метод для каждой псевдо-константы, - это путь:

public interface IVariableProvider {
    public int maxGravity();
    public int maxSpeed();
    // and everything else...
}

public class VariableProvider {
    private final int maxGravity, maxSpeed...;
    public VariableProvider(int maxGravity, int maxSpeed) {
        // assign final fields
    }
}

Тогда я могу сделать:

Model firstModel = new Model(new VariableProvider(2, 10));  
Model secondModel = new Model(new VariableProvider(10, 100));  

Я думаю, что до тех пор, пока интерфейс не предоставляет чрезмерно большое количество переменных-получателей, он выигрывает у некоторого параметризованного поиска (который будет уязвим во время выполнения или запретит расширение / полиморфизм).

P.S. Я понимаю, что некоторые задаются вопросом, что моя проблема со статическими конечными значениями. Я сделал заявление (с языком в щеку) коллеге, что все статическое по своей сути не объектно-ориентировано. Поэтому в своем хобби я использовал это в качестве основы для мыслительного упражнения, в котором я пытаюсь удалить что-либо статичное из проекта (затем я попытаюсь удалить все операторы «если» ;-D). Если бы у меня был крайний срок, и я был удовлетворен тем, что общедоступные конечные статические значения не помешали бы тестированию, я бы использовал их довольно быстро.

0 голосов
/ 10 февраля 2009

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

Если вы просто хотите «объективировать» константы, хотя, по какой-то причине, вероятно, потребуется шаблон Singleton, если таковой имеется; Я знаю, что вы упомянули в комментарии, что вы не возражаете против создания нескольких экземпляров этого объекта-обертки, но в ответ я бы спросил, зачем тогда вообще вводить в заблуждение тот тип, который может возникнуть из-за наличия нескольких экземпляров? Какую практическую выгоду вы ищете для удовлетворения данных в виде объекта?

Теперь, если значения не являются константами, тогда все по-другому - в этом случае вы, вероятно, захотите использовать Singleton или Monostate. Но если они действительно являются константами, просто оберните набор перечислений или статических констант в классе и все готово! Keep-it-simple - такой же хороший «шаблон», как и любой другой.

0 голосов
/ 09 февраля 2009

Если вы просто используете java / IOC, почему бы просто не ввести значения зависимостями?

например. Spring вводит значения через карту, указывает объект как одиночный -

<property name="values">
    <map>
        <entry> <key><value>a1</value></key><value>b1</value></entry>
        <entry> <key><value>a2</value></key><value>b3</value></entry>
    </map>
  </property>

ваш класс представляет собой синглтон, который содержит неизменную копию карты, установленной весной -

private Map<String, String> m;

public String getValue(String s)
{
  return m.containsKey(s)?m.get(s):null;
}

public void setValues(Map m)
{
  this.m=Collections.unmodifiableMap(m):
}
...