Null object (шаблон проектирования)
Из Википедии, бесплатной энциклопедии
В объектно-ориентированном программировании Null Object — это объект с определенным нейтральным («null») поведением. Шаблон проектирования Null Object описывает использование таких объектов и их поведение (или отсутствие такового). Впервые опубликован в серии книг Pattern Languages of Program Design.[1]
Описание[править | править код]
В таких объектно-ориентированных языках как Java или C# объекты могут иметь значение NULL. Ссылки на такие объекты нуждаются в проверке на NULL-значение перед использованием, так как методы класса «нулевого» объекта, как правило, не могут вызываться.
Целью Null-object'а является инкапсулирование отсутствия объекта путём замещения его другим объектом, который ничего не делает.
Данный шаблон проектирования рекомендуется использовать, когда:
- Объект требует взаимодействия с другими объектами. Null Object не устанавливает нового взаимодействия — он использует уже установленное взаимодействие.
- Какие-то из взаимодействующих объектов должны бездействовать.
- Требуется абстрагирование «общения» с объектами, имеющими NULL-значение.[2]
Плюсы[править | править код]
- Снижаются шансы на ошибку — не произойдёт разыменование нулевого указателя, потому что его нет.
Минусы[править | править код]
- Могут неоправданно включаться дополнительные механизмы языка программирования вроде выделения памяти и виртуального полиморфизма.
- Если интерфейс сложный, нужно много нетворческого кода.
- Если перед вызовом происходит сложная подготовка, всё равно приходится спрашивать у объекта, делает ли он что-то — но это лишь дополнительная оптимизация, не ведущая к моментальному отказу программы.
// Для ясности функции с разными сигнатурами зовутся разными именами. // Тут никаких вопросов. logger.put("Program started."); // Запускается тяжёлый format, даже если журнала нет logger.put(std::format("a={}, b={}", a, b)); // Тут format запускается, только если logger реально пишет if (logger.isWriting()) { logger.put(std::format("a={}, b={}", a, b)); } // Два способа решить, со своими достоинствами и недостатками logger.format("a={}, b={}", a, b); logger.putObj(LazyFormat{"a={}, b={}", a, b});
Структура[править | править код]
На диаграмме классов в языке UML шаблон проектирования представлен следующим образом:
Примеры[править | править код]
Пример на C#
/* * Пример применения шаблона Null Object: */ void Main() { AbstractEntity realEntity = new RealEntity(); realEntity.doSomething(); // RealEntity::doSomething AbstractEntity unknownEntity = new NullEntity(); unknownEntity.doSomething(); // no output } // Define other methods and classes here public abstract class AbstractEntity { public abstract void doSomething(); } public class RealEntity : AbstractEntity { public override void doSomething() { Console.WriteLine("RealEntity::doSomething"); } } public class NullEntity : AbstractEntity { public override void doSomething() { // doing nothing } }
Пример на PHP
/* * Пример применения шаблона Null Object: */ declare(strict_types=1); namespace DesignPatterns\Behavioral\NullObject; class Service { public function __construct(private Logger $logger) { } /** * do something ... */ public function doSomething() { // notice here that you don't have to check if the logger is set with eg. is_null(), instead just use it $this->logger->log('We are in ' . __METHOD__); } } /** * Key feature: NullLogger must inherit from this interface like any other loggers */ interface Logger { public function log(string $str); } class PrintLogger implements Logger { public function log(string $str) { echo $str; } } class NullLogger implements Logger { public function log(string $str) { // do nothing } } $servicePrint = new Service(new PrintLogger()); $servicePrint->doSomething(); // 'We are in DesignPatterns\Behavioral\NullObject\Service::doSomething' $serviceNull = new Service(new NullLogger()); $serviceNull->doSomething(); // (do nothing)
Пример на Java
/* * Pattern Null object. */ public class Main { public static void main(String[] args) { AbstractEntity realEntity = new RealEntity(); realEntity.doSomething(); // RealEntity::doSomething AbstractEntity unknownEntity = new NullEntity(); unknownEntity.doSomething(); // no output } } abstract class AbstractEntity { public abstract void doSomething(); } class RealEntity extends AbstractEntity { @Override public void doSomething() { System.out.println("RealEntity::doSomething"); } } class NullEntity extends AbstractEntity { @Override public void doSomething() { } }
Пример на Python
# Pattern Null object. class AbstractEntity: def doSomething(self): pass class RealEntity(AbstractEntity): def doSomething(self): print("RealEntity.doSomething") class NullEntity(AbstractEntity): def doSomething(self): pass def main(): real_entity = RealEntity() real_entity.doSomething() unknown_entity = NullEntity() unknown_entity.doSomething() if __name__ == "__main__": main()
Пример на Ruby[править | править код]
module NullObject # AbstractEntity class AbstractEntity def doSomething raise NoMethodError.new end end # RealEntity class RealEntity < AbstractEntity def doSomething puts "RealEntity > Do Something" end end # NullEntity class NullEntity < AbstractEntity def doSomething nil end end end # Client module Client include NullObject realEntity = RealEntity.new nullEntity = NullEntity.new puts "RealEntity:" # => RealEntity realEntity.doSomething # => RealEntity > Do Something puts "NullEntity:" # => NullEntity: nullEntity.doSomething # not output end
Примечания[править | править код]
- ↑ Woolf, Bobby. Pattern Languages of Program Design 3 (неопр.) / Martin, Robert; Riehle, Dirk; Buschmann, Frank. — Addison-Wesley, 1998.
- ↑ http://sourcemaking.com/design_patterns/null_object Архивная копия от 15 июня 2012 на Wayback Machine SourceMaking Tutorial
Ссылки[править | править код]
- 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
В другом языковом разделе есть более полная статья Null object pattern (англ.). |
Это заготовка статьи о программном обеспечении. Помогите Википедии, дополнив её. |