Мой ответ не будет наиболее информативным, однако он будет получен из непосредственного опыта работы с этим шаблоном. При проектировании объекта часто возникает соблазн напрямую обращаться к полям-членам, а не полагаться на аксессуры. Желание проистекает из желания упростить объект и избежать добавления беспорядка из методов, которые просто возвращают значение. Берем пример еще один шаг, чтобы добавить Context & значение:
public class MyClassmate {
private Integer age;
public MyClassmate(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
}
Здесь возраст является простым числом, и кажется ненужным добавить геттеры/сеттеры вокруг него. Если мы добавим следующий метод вы бы искушен непосредственно доступа к полю, так как нет никаких изменений в поведении:
public Integer calculateScore() {
if(age > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
Ваш объект может затем расти новые функции с помощью методов, опирающихся на поле возраста, где вы будете продолжать использовать его непосредственно. Позже вы можете изменить способ создания возраста и вывести его из сети. Возможно, вы не захотите включить сетевую логику в конструктор, потому что это дорогостоящая операция, которая должна запускаться только по мере необходимости. Метод calculateScore()
мог бы установить сетевое соединение и узнать возраст, но тогда все остальные методы полагались бы на возраст. Но что, если calculateScore выглядел следующим образом ?:
public Integer calculateScore() {
if(getAge() > 21) return 100 - getNumberOfIncorrectAnswers();
//Add 10% before for younger students
else return (100 - getNumberOfIncorrectAnswers()) + 10;
}
Затем можно повысить объект меняющийся, как он производный возраст, не касаясь метода calculateScore()
. Это означает, что ваш метод следует принципу Open Closed (OCP). Он открыт для улучшения, но закрыт для изменения, или вам не нужно было менять источник метода, чтобы изменить его возраст.
В зависимости от сложности вашего приложения и объектной модели все еще могут быть случаи, когда инкапсулированный доступ является чрезмерным, но даже в этих сценариях хорошо понимать компромиссы прямого доступа к полям, и эти более упрощенные сценарии в основном редки.
В общем, вы должны понимать, что потребность в инкапсуляции почти никогда не бывает незамедлительной. С течением времени, когда объект растет, и если объект не настроен с инкапсуляцией с его начала, более дорого его фазировать. Именно поэтому этот подход так трудно оценить. Требуется опыт (т. Е. Сделать типичное упрощение и страдания несколько раз в течение нескольких лет) до чувствовать себя, почему требуется инкапсуляция.Это не то, что вы можете наблюдать и обнаруживать.
Сказали, что раньше это была гораздо большая проблема, чем сегодня, когда IDE были не такими полнофункциональными. Сегодня вы можете использовать встроенный рефакторинг encapsulate fields
в некоторых IDE, таких как IntelliJ, чтобы представить шаблон по мере необходимости. Даже с современными IDE по-прежнему выгодно практиковать инкапсуляцию с самого начала.
Если вы идете по инкапсуляции и абстракции Java, я думаю, что сначала предпочтительнее. Поскольку вы не открываете поля непосредственно. – SachinSarawgi
Разница в смысле не имеет значения. Это скорее вопрос. Я бы выбрал ** реализацию 1 **, так как вы обязательно получите значение, которое хотите проверить, если у вас есть, например, какой-либо транскодификационный код – DamCx
. Вы должны внимательно прочитать: http: // stackoverflow .com/questions/1568091/why-use-getters-and-setters – rafid059