Null object (шаблон проектування)
В об'єктно-орієнтованому програмуванні, Null Object або нульовий об'єкт — це об'єкт з визначеною нейтральною (англ. null) поведінкою. Шаблон проектування Null Object описує використання цих об'єктів та їх поведінки або відсутності таких. Вперше цей шаблон було описано в серії книжок Pattern Languages of Program Design.[1]
Зміст |
Мотивація [ред.]
У більшості об'єктно-орієнтованих мов програмування, таких як Java або C#, посилання можуть приймати значення null. Це значення говорить про те, що за посиланням не існує реального об'єкту і виклик методів може призвести до численних помилок та краху системи.
Традиційно, методи, що повертають об'єкти (наприклад, методи твірних шаблонів) у випадку невдачі (наприклад, пошук об'єкту в порожній колекції) повинні повертати коректне значення посилання — null.
Обробка цього результату може бути реалізована простою перевіркою посилання на null перед викликом методів.
// Приклад на Java class Animal { public void makeSound() { System.out.write("Гав-гав!"); } } ... Animal pet = animalsProvider.getAnimal(); if (pet != null) { pet.makeSound(); } else { /* обробка помилки */ } ...
Проблему обробки null-посилань і вирішує шаблон Null object.
Треба відзначити, що, наприклад, у мові програмування Objective-C використовується інший підхід до цієї проблеми: всі методи, що викликаються через nil-посилання (nil близька за сенсом до null частина Objective-C) повертають також nil.
Опис [ред.]
Замість використання null-посилання для відображення відсутності об'єкту треба використовувати спеціальний об'єкт, який реалізує потрібні інтерфейси, але не має поведінки, тобто має пусті методи. Перевагою цього підходу є те, що реалізація нульового об'єкту завжди передбачувана: вона нічого не робить, а тому не має таких побічних ефектів, які має null-посилання.
Наприклад, функція повинна прочитати список файлів в директорії та виконати якісь дії з кожним. В випадку, якщо директорія порожня, можна повернути null або згенерувати виняток. Таким чином, код, що очікує список файлів повинен перевіряти, чи дійсно він отримав список, а це в свою чергу ускладнює структуру програми.
Якщо повертати нульовий об'єкт (наприклад, порожній список), то зникає необхідність перевірок. Викликаючий код може ітерувати список файлів, не зважаючи на можливі помилки і не виконувати ніяких дій при цьому.
Хоча, залишається можливим робити дещо змінену перевірку: «чи дорівнює результат нульовому об'єкту?», та діяти далі за логікою програми.
Також, цей шаблон може використовуватися як заглушка при тестуванні.
Відношення до інших шаблонів [ред.]
Шаблон може розглядатися як спеціальний випадок шаблонів Стан (англ. State) та Стратегія (англ. Strategy). Він не написаний в книзі GoF, а був запропонований Мартіном Фаулером[2] та Джошуа Керієвскі[3].
В мовах [ред.]
C++ [ред.]
Мова зі статично типізованими посиланнями на об'єкти показує, як нульовий об'єкт стає складнішим шаблоном.
class animal { public: virtual void make_sound() = 0; }; class dog : public animal { void make_sound() { cout << "woof!" << endl; } }; class null_animal : public animal { void make_sound() { } };
Існують ситуації, коли вказівник або посилання на об'єкт класу animal необхідний, але за ним немає належного об'єкту. Посилання не може бути null, коли вказівник animal * — може: такий вказівник можна використовувати для зберігання об'єкту, але неможливо безпосередньо викликати методи. Код a->make_sound() викличе помилку undefined behavior (укр. невизначена поведінка), якщо a буде null-вказівником.
Шаблон Null object вирішує цю проблему, впроваджуючи спеціальний клас null_animal, який може бути інстанційований та викорстовуватись з вказівником чи посиланням на animal.
C# [ред.]
С# є мовою, в якій шаблон Null object можна реалізувати канонічно. В нижче наведеному прикладі, нульовий об'єкт реалізує очікувану порожню поведінку та попереджає проблеми часу виконання програми, а сам виняток Null Reference Exception, який буде згенеровано, якщо відбудеться використання null-посилання.
using System; interface Animal { void MakeSound(); } class Dog : Animal { public void MakeSound() { Console.WriteLine("Woof!"); } } class NullAnimal : Animal { public void MakeSound() { } } static class Program { static void Main() { Animal dog = new Dog(); dog.MakeSound(); // Animal unknown = new NullAnimal(); //<< замінює: Animal unknown = null; unknown.MakeSound(); // нічого не відбувається } }
Smalltalk [ред.]
За принципом Smalltalk, «все є об'єктом», відсутність якогось об'єкту моделюється об'єктом nil. В GNU Smalltalk, наприклад, nil є об'єктом класу UndefinedObject, прямого нащадка Object.
Будь-яка операція, яка не змогла повернути потрібний об'єкт може повернути nil замість нього, таким чином, попереджаючи повернення «об'єкту нема». Цей підхід спрощує програму, позбавляючи від null-посилань, null-вказівників.
Ruby [ред.]
В Ruby нульвоий об’єкт це повноцінний об’єкт класу NilClass. Він специфічним чином працює в логічних виразах: він приймає значення false. Ruby дозволяє розширювати цей клас, тому, якщо ви хочете таку ж поведінку, як у в Objective-C, тоді використовуйте щось на кшталт цього:
class NilClass def method_missing(*) return nil end end
Див. також [ред.]
Посилання [ред.]
- Jeffrey Walkers' account of the Null Object Pattern
- Martin Fowlers' description of Special Case, a slightly more general pattern
- Null Object Pattern Revisited
- Introduce Null Object refactoring
- SourceMaking Tutorial
Примітки [ред.]
- ↑ Woolf, Bobby (1998). «Null Object». У Martin, Robert; Riehle, Dirk; Buschmann, Frank. Pattern Languages of Program Design 3. Addison-Wesley.
- ↑ Fowler, Martin (1999). Refactoring. Improving the Design of Existing Code. Addison-Wesley. ISBN 0-201-48567-2.
- ↑ Kerievsky, Joshua (2004). Refactoring To Patterns. Addison-Wesley. ISBN 0-321-21335-1.
| На цю статтю не посилаються інші статті Вікіпедії.
Будь ласка, скористайтеся підказкою та розставте посилання відповідно до прийнятих рекомендацій.
|