Я работаю над кодом пользовательского интерфейса, где у меня есть Action
класс, что-то вроде этого -
public class MyAction extends Action {
public MyAction() {
setText("My Action Text");
setToolTip("My Action Tool tip");
setImage("Some Image");
}
}
Когда этот класс Action был создан, предполагалось, что Action
класс не будет настраиваемым (в некотором смысле - его текст, всплывающая подсказка или изображение не будут изменены нигде в коде). Теперь нам нужно изменить текст действия в каком-то месте кода. Итак, я предложил моему коллеге удалить жестко закодированный текст действия из конструктора и принять его в качестве аргумента, чтобы каждый был вынужден передать текст действия. Примерно такой код ниже -
public class MyAction extends Action {
public MyAction(String actionText) {
setText(actionText);
setTooltip("My Action tool tip");
setImage("My Image");
}
}
Однако он считает, что поскольку setText()
метод принадлежит базовому классу, его можно гибко использовать для передачи текста действия везде, где создается экземпляр действия. Таким образом, нет необходимости менять существующий MyAction
класс. Так что его код будет выглядеть примерно так.
MyAction action = new MyAction(); //this creates action instance with the hardcoded text
action.setText("User required new action text"); //overwrite the existing text.
Я не уверен, что это правильный способ решения проблемы. Я думаю, что в вышеупомянутом случае пользователь все равно собирается изменить текст, так почему бы не заставить его при создании действия? Единственное преимущество, которое я вижу с оригинальным кодом, заключается в том, что пользователь может создавать класс Action, не задумываясь о настройке текста.
Ответы:
Это на самом деле не является преимуществом, для большинства целей это недостаток, а в остальных случаях я бы назвал это ничьей. Что если кто-то забудет вызвать setText () после создания? Что, если это так в каком-то необычном случае, возможно, в обработчике ошибок? Если вы действительно хотите, чтобы текст был установлен, вы должны принудительно установить его во время компиляции, поскольку только ошибки времени компиляции на самом деле являются фатальными . Все, что происходит во время выполнения, зависит от того, какой конкретный путь к коду выполняется.
Я вижу два ясных пути вперед:
null
или пустую строку, но тогда факт, что вы не назначаете текст, является явным, а не неявным. Легко увидеть существованиеnull
параметра и увидеть, что, возможно, в него была вложена некоторая мысль, но не так легко увидеть отсутствие вызова метода и определить, было ли отсутствие такого намеренным или нет. Для такого простого случая, как этот, я бы выбрал такой подход.источник
Перегрузка конструктора была бы простым и понятным решением:
Это лучше, чем звонить
.setText
позже, потому что таким образом ничего не нужно перезаписывать, оноactionText
может быть намеченным с самого начала.По мере развития вашего кода, и вам понадобится еще больше гибкости (что, безусловно, произойдет), вы извлечете выгоду из паттерна фабрики / сборки, предложенного другим ответом.
источник
Добавьте свободный метод setText:
Что может быть понятнее этого? Если вы решите добавить другое настраиваемое свойство, нет проблем.
источник
setText()
он определен в классе Action, от которого наследуется MyAction. Вероятно, он уже имеет тип возврата void.Как сказал Кевин Клайн в своем ответе, я думаю, что лучше всего создать свободный API . Я просто хотел бы добавить, что свободный API работает лучше, когда у вас есть более одного свойства, которое вы можете использовать.
Это сделает ваш код более читабельным, и, с моей точки зрения, более простым и, ах , «сексуальным» для написания.
В вашем случае все будет так (извините за опечатку, прошел год с тех пор, как я написал свою последнюю Java-программу):
И использование будет таким:
источник
В общем, совет использовать конструкторов или конструкторов, но, по моему опыту, упускает некоторые ключевые моменты для действий, которые
Я настоятельно рекомендую прочитать имя, всплывающую подсказку, значок и т. Д. Из файла свойств, XML и т. Д. Например, для действия «Открыть файл» можно передать свойства и выполнить поиск
Этот формат довольно легко перевести на французский, попробовать новую лучшую иконку и т. Д. Без времени программиста или перекомпиляции.
Это всего лишь грубый набросок, многое остается для читателя ... Ищите другие примеры интернационализации.
источник
Бесполезно вызывать setText (actionText) или setTooltip («Моя подсказка действия») внутри конструктора; это проще (и вы получаете больше производительности), если вы просто инициализируете соответствующее поле напрямую:
Если вы измените actionText в течение срока службы соответствующего объекта MyAction, вы должны разместить метод установки; если нет, инициализируйте поле только в конструкторе, не предоставляя метод установки.
Поскольку всплывающая подсказка и изображение являются константами, рассматривайте их как константы; есть поля:
На самом деле, при проектировании общих объектов (не bean-объектов или объектов, представляющих строго структуры данных) плохая идея предоставлять сеттеры и геттеры, поскольку они как бы нарушают инкапсуляцию.
источник
Я думаю, что это правда, если мы собираемся создать общий класс действий (например, update, который используется для обновления Employee, Department ...). Все зависит от сценария. Если создается определенный класс действия (например, обновить сотрудника) (который часто используется в приложении - Обновить сотрудника) с намерением сохранить один и тот же текст, всплывающую подсказку и изображение в каждом месте приложения (с точки зрения согласованности). Таким образом, жесткое кодирование может быть выполнено для текста, всплывающей подсказки и изображения, чтобы предоставить текст по умолчанию, всплывающую подсказку и изображение. Тем не менее, чтобы дать больше гибкости, чтобы настроить их, он должен иметь соответствующие методы установки. Имея в виду только 10% мест, мы должны это изменить. Принятие текста действия каждый раз от пользователя может вызывать разные тексты каждый раз для одного и того же действия. Например, «Обновить Emp», «Обновить сотрудника», «Изменить сотрудника» или «Редактировать сотрудника».
источник
Подумайте, как будут использоваться экземпляры, и используйте решение, которое будет направлять или даже заставлять пользователей использовать эти экземпляры правильным или, по крайней мере, наилучшим образом. Программисту, использующему этот класс, будет о чем беспокоиться и о чем подумать. Этот класс не следует добавлять в список.
Например, если класс MyAction должен быть неизменным после построения (и, возможно, другой инициализации), у него не должно быть метода установки. Если большую часть времени он будет использовать «Текст моего действия» по умолчанию, должен быть конструктор без параметров, плюс конструктор, который допускает необязательный текст. Теперь пользователю не нужно думать, чтобы использовать класс правильно 90% времени. Если пользователь обычно должен задуматься над текстом, пропустите конструктор без параметров. Теперь пользователь вынужден думать, когда это необходимо, и не может пропустить необходимый шаг.
Если
MyAction
экземпляр должен быть изменчивым после полной конструкции, тогда вам нужен установщик для текста. Соблазнительно пропустить установку значения в конструкторе (принцип СУХОГО - «Не повторяй себя»), и, если значение по умолчанию обычно достаточно хорошее, я бы это сделал. Но если это не так, требование текста в конструкторе заставляет пользователя думать, когда он должен.Обратите внимание, что эти пользователи не глупы . У них просто слишком много реальных проблем, о которых нужно беспокоиться. Думая об «интерфейсе» вашего класса, вы можете не допустить, чтобы он стал реальной проблемой - и ненужной.
источник
В следующем предложенном решении суперкласс является абстрактным и для всех трех членов установлено значение по умолчанию.
У подкласса есть различные конструкторы, так что программист может создать его экземпляр.
Если используется первый конструктор, все члены будут иметь значения по умолчанию.
Если используется второй конструктор, вы даете начальное значение члену actionText, оставляя двум другим членам значение по умолчанию ...
Если используется третий конструктор, вы создаете его экземпляр с новым значением для actionText и toolTip, оставляя imageURl со значением по умолчанию ...
И так далее.
источник