Код типу:
public Thing[] getThings(){
return things;
}
Це не має особливого сенсу, оскільки ваш метод доступу не робить нічого, крім прямого повернення внутрішньої структури даних. Ви можете також просто заявити Thing[] things
про своє public
. Ідея методу доступу полягає в створенні інтерфейсу, який захищає клієнтів від внутрішніх змін і не дозволяє їм маніпулювати фактичною структурою даних, за винятком дискретних способів, дозволених інтерфейсом. Як ви дізналися, коли зламався весь код вашого клієнта, ваш метод доступу цього не зробив - це просто марний код. Я думаю, що багато програмістів прагнуть писати подібний код, тому що вони десь дізналися, що все потрібно інкапсулювати методами доступу - але це з тих причин, які я пояснив. Робити це просто для "слідування за формою", коли метод доступу не виконує жодної мети - це лише шум.
Я б точно рекомендував запропоноване вам рішення, яке реалізує деякі найважливіші цілі інкапсуляції: надання клієнтам надійного, стриманого інтерфейсу, який ізолює їх від внутрішніх деталей реалізації вашого класу та не дозволяє їм торкатися внутрішньої структури даних. очікуйте способів, які ви вирішите прийнятними - "закон найменш необхідної пільги". Якщо ви подивитеся на великі популярні рамки OOP, такі як CLR, STL, VCL, запропонований вами шаблон є широко поширеним саме з цієї причини.
Ви завжди повинні це робити? Не обов'язково. Наприклад, якщо у вас є класи помічників або друзів, які по суті є складовою вашого основного класу робітників і не є "передньою", це не обов'язково - це зайвий збиток, який додасть багато непотрібного коду. І в такому випадку я б взагалі не використовував метод доступу - це безглуздо, як пояснено. Просто оголосіть структуру даних у такий спосіб, який охоплюється лише до основного класу, який її використовує - більшість мов підтримують способи цього - friend
або оголошуючи її у тому ж файлі, що і основний клас робітників тощо.
Єдиний недолік, який я бачу у вашій пропозиції, полягає в тому, що потрібно більше кодувати (і тепер вам доведеться перекодувати свої споживчі класи - але все одно ви повинні / повинні були це зробити.) Але це насправді не є недоліком - потрібно робити це правильно, а іноді це вимагає більше роботи.
Одна з речей, яка робить хорошого програміста хорошим - це те, що вони знають, коли додаткова робота варта, а коли ні. Зрештою, введення додаткових коштів тепер окупиться великими дивідендами - якщо не за цим проектом, то за іншими. Навчіться правильно кодувати і користуватися головою про це, а не лише робототехнічно виконувати встановлені форми.
Зауважте, що для колекцій, складніших за масиви, можливо, зажадає клас, що додає, щоб реалізувати навіть більше трьох методів лише для доступу до внутрішньої структури даних.
Якщо ви відкриваєте всю структуру даних через клас, що містить ІМО, вам потрібно подумати про те, чому цей клас взагалі інкапсульований, якщо це не просто забезпечити більш безпечний інтерфейс - "клас обгортки". Ви говорите, що містить клас для цієї мети не існує - тому, можливо, у вашому дизайні щось не так. Подумайте про розбиття своїх класів на більш стримані модулі та їх розшарування.
Клас повинен мати одне чітке і стримане призначення і надати інтерфейс для підтримки цієї функціональності - не більше. Можливо, ви намагаєтесь зв’язати речі, які не належать один одному. Коли ви це зробите, все буде порушуватися щоразу, коли вам доведеться ввести зміни. Чим менші та більш дискретні ваші заняття, тим легше змінювати речі: Подумайте LEGO.
get(index)
,add()
,size()
,remove(index)
, іremove(Object)
. Використовуючи запропоновану техніку, клас, який містить цей ArrayList, повинен мати п'ять відкритих методів, щоб делегувати їх до внутрішньої колекції. І мета цього класу в програмі, швидше за все, не інкапсулює цей ArrayList, а скоріше робить щось інше. ArrayList - лише деталь. [...]