Java: как обработать МНОГО полей и их инкапсуляции чисто?

Вы можете использовать регулярное выражение (\w+.nc\b|\b\w+\b[^.]). Он будет захватывать что-то вроде abc.nc и abc, но не abc.rc, поэтому он будет захватывать только необходимое расширение или без расширения.

10
задан cherouvim 20 April 2009 в 15:35
поделиться

10 ответов

Мой опыт показывает, что в ситуациях, когда вам нужно много полей, число, природа Имена и типы полей настолько гибки и могут изменяться в течение всего жизненного цикла вашего проекта, поэтому вам, скорее всего, понадобится какая-то карта вместо полей.

Например, имейте карту атрибутов от ключей к значениям.

Обеспечьте публичные вызовы для получения и установки атрибутов, но не позволяйте всем использовать их (или убедитесь, что они не используют). Вместо этого создайте классы для представления каждого интересующего вас атрибута, и этот класс предоставляет все функции для управления этим атрибутом. Например, если у вас есть Strength, вы можете иметь класс «StrengthManipulation», который инициализируется для конкретного объекта Player, а затем предоставляет геттеры, сеттеры (все с соответствующей проверкой и исключениями) и, возможно, такие вещи, как вычисление силы с помощью бонусов и т. д.

Одним из преимуществ этого является то, что вы отделяете использование своих атрибутов от класса игрока. Поэтому, если вы сейчас добавите атрибут интеллекта, вам не придется разбирать и перекомпилировать все, что манипулирует только силой.

Что касается прямого доступа к полям, это плохая идея. Когда вы получаете доступ к полю в VB (по крайней мере, в старых VB), вы обычно вызываете getter и setter свойства, а VB просто скрывает для вас вызов (). Я считаю, что вы должны адаптироваться к соглашениям языка, который вы используете. В C, C ++, Java и т. Д. У вас есть поля и у вас есть методы. Вызов метода должен всегда иметь (), чтобы было ясно, что это вызов и могут происходить другие вещи (например, вы можете получить исключение). В любом случае, одним из преимуществ Java является более точный синтаксис и стиль.

VB на Java или C ++ - это то же самое, что текстовые сообщения, чтобы закончить научное письмо.

Кстати: некоторые исследования юзабилити показывают, что лучше не иметь параметров для конструкторов, а скорее создавать и вызывать все сеттеры, если они вам нужны.

8
ответ дан 3 December 2019 в 14:06
поделиться

У Стива Йегге было очень интересное (хотя и продолжительное) сообщение в блоге, в котором освещались следующие проблемы: Шаблон универсального дизайна .

4
ответ дан 3 December 2019 в 14:06
поделиться

Похоже, вы думаете с точки зрения if (player.dexterity> monster.dexterity) attacker = игрок . Вам нужно больше думать, как if (player.quickerThan (monster)) monster.suffersAttackFrom (player.getCurrentWeapon ()) . Не возитесь с голой статистикой, выражайте свое реальное намерение, а затем разрабатывайте свои занятия так, как они должны делать. Статистика в любом случае отговорка; что вас действительно волнует, так это то, может или нет игрок выполнять какие-либо действия, или его способность / способность в сравнении с некоторыми рекомендациями. Думайте в терминах «достаточно ли силен персонаж игрока» ( player.canOpen (trapDoor) ) вместо «обладает ли персонаж как минимум 50 силой».

18
ответ дан 3 December 2019 в 14:06
поделиться
[113615 Для меня это выглядит так, как будто «thisCharacter» вполне может иметь «интеллектуальный» объект для работы с интеллектом за кулисами, но я сомневаюсь, должен ли он вообще быть публичным. Вы должны просто предоставить thisCharacter.applyInt и thisCharacter.getInt вместо объекта, который имеет с ним дело. Не выставляйте свою реализацию таким образом.

2
ответ дан 3 December 2019 в 14:06
поделиться

Держите ваши поля приватными! Вы никогда не хотите показывать слишком много вашего API. В будущих выпусках вы всегда можете сделать что-то частное, но не наоборот.

Подумайте, как если бы вы сделали это в следующей MMORPG. У вас будет много возможностей для ошибок, ошибок и ненужного зла. Убедитесь, что неизменяемые свойства являются окончательными.

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

2
ответ дан 3 December 2019 в 14:06
поделиться

То, что вы, по-видимому, имеете здесь, является одним слоем составной модели.

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

Поля должны быть окончательными, поэтому, даже если вы сделаете их общедоступными, вы не сможете случайно присвоить им null.

Префикс «get» присутствует для всех геттеров, поэтому это, вероятно, скорее первоначальный вид, чем новая проблема как таковая.

1
ответ дан 3 December 2019 в 14:06
поделиться

In addition to Uri's answer (which I totally support), I'd like to suggest you consider defining the attribute map in data. This will make your program EXTREMELY flexible and will factor out a lot of code you don't even realize you don't need.

For instance, an attribute can know what field it binds to on the screen, what field it binds to in the database, a list of actions to execute when the attribute changes (a recalculate hit% might apply to both strength and dex...)

Doing it this way, you have NO code per attribute to write a class out to the DB or display it on the screen. You simply iterate over the attributes and use the information stored inside.

The same thing can apply to skills--in fact, attributes and skills would probably derive from the same base class.

After you go down this road, you'll probably find yourself with a pretty serious text file to define attributes and skills, but adding a new skill would be as easy as:

Skill: Weaving
  DBName: BasketWeavingSkill
  DisplayLocation: 102, 20  #using coordinates probably isn't the best idea.
  Requires: Int=8
  Requires: Dex=12
  MaxLevel=50

At some point, adding a skill like this would require no code change whatsoever, it could all be done in data pretty easily, and ALL the data is stored in a single skill object attached to a class. You could, of course, define actions the same way:

Action: Weave Basket
  text: You attempt to weave a basket from straw
  materials: Straw
  case Weaving < 1
    test: You don't have the skill!
  case Weaving < 10
    text: You make a lame basket
    subtract 10 straw
    create basket value 8
    improve skill weaving 1%
  case Weaving < 40
    text: You make a decent basket
    subtract 10 straw
    create basket value 30
    improve skill weaving 0.1%
  case Weaving < 50
    text: You make an awesome basket!
    subtract 10 straw
    create basket value 100
    improve skill weaving 0.01%
  case Weaving = 50
    text: OMG, you made the basket of the gods!
    subtract 10 straw
    create basket value 1000

Although this example is pretty advanced, you should be able to visualize how it would be done with absolutely no code. Imagine how difficult it would be to do anything like that without code if your "attributes/skills" were actually member variables.

0
ответ дан 3 December 2019 в 14:06
поделиться

Преимущества инкапсуляции настолько велики, что я должен идти вперед и иметь геттерные геттеры и сеттеры-геттеры и так далее ... ... или я должен принять инкапсуляцию в здоровых мерах и оставить Поле как открытое поле?

ИМО, инкапсуляция не имеет ничего общего с обертыванием геттера / установщика вокруг частного поля. В небольших дозах или при написании библиотек общего назначения компромисс приемлем. Но когда в системе, подобной той, которую вы описываете, не отмечено, то это антипаттерн .

Проблема с геттерами / сеттерами заключается в том, что они создают чрезмерно тесную связь между объектом с этими методами и остальная часть системы.

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

Вместо того, чтобы показывать реализацию GameCharacter с помощью setIntelligence, почему бы не дать GameCharacter интерфейс, который лучше отражает его роль в игровой системе?

Например, вместо :

// pseudo-encapsulation anti-pattern
public class GameCharacter
{
  private Intelligence intelligence;

  public Intelligence getIntelligence()
  {
    return intelligence
  }

  public void setIntelligence(Intelligence intelligence)
  {
    this.intelligence = intelligence;
  }
}

почему бы не попробовать это?:

// better encapsulation
public class GameCharacter
{
  public void grabObject(GameObject object)
  {
    // TODO update intelligence, etc.
  }

  public int getIntelligence()
  {
    // TODO
  }
}

или даже лучше:

// still better
public interface GameCharacter
{
  public void grabObject(GameObject object); // might update intelligence
  public int getIntelligence();
}

public class Ogre implements GameCharacter
{
  // TODO: never increases intelligence after grabbing objects
}

Другими словами, GameCharacter может захватывать объекты GameObject. Эффект каждого захвата GameCharacter одного и того же GameObject может (и должен) различаться, но детали полностью инкапсулированы в каждой реализации GameCharacter.

Обратите внимание, как GameCharacter теперь отвечает за обработку своего собственного обновления интеллекта (проверка диапазона и т. Д.). ), что может произойти, например, при захвате GameObjects. Сеттер (и осложнения, которые вы отмечаете при его наличии) исчезли. Возможно, вам удастся вообще отказаться от метода getIntelligence, в зависимости от ситуации. Аллен Голуб приводит эту идею к своему логическому завершению , но этот подход, похоже, не очень распространен.

1
ответ дан 3 December 2019 в 14:06
поделиться

Похоже, ваша главная жалоба связана не столько с абстракцией методов сеттера / геттера, сколько с языком синтаксис для их использования. Т.е. вы бы предпочли что-то вроде свойств стиля C #.

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

Конечно, если платформа Java является требование, но язык не значит, есть другие альтернативы. Например, у Scala очень хороший синтаксис свойств, а также множество других функций, которые могут быть полезны для такого проекта. И что лучше всего, он работает на JVM, поэтому вы все равно получаете такую ​​же мобильность, как Получил, написав это на языке Java. :)

1
ответ дан 3 December 2019 в 14:06
поделиться

Подумайте об использовании "моделирующей" среды, такой как EMF Eclipse. Это включает в себя определение ваших объектов, используя что-то вроде редактора Eclipse EMF, или в простом XML, или в Rational Rose. Это не так сложно, как кажется. Вы определяете атрибуты, ограничения и т. Д. Затем каркас генерирует код для вас. Добавляет теги @generated к частям, таким как методы получения и установки. Вы можете настроить код, а затем редактировать или вручную, или через некоторый графический интерфейс, и восстановите файлы Java.

0
ответ дан 3 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: