IT Notes

Паттерн Null Object

Паттерн Null Object является довольно простой концепцией ООП, но легко позволяет устранить ненужные условные конструкции и тем самым упростить понимание кода. Для этого и предназначен полиморфизм в первую очередь.

Идея паттерна Null Object заключается в том, что в качестве одной из реализаций некоторого интерфейса добавляется Null-класс, который обладает нейтральным поведением. Учтите, что он не может быть абстрактным, поскольку ожидается создание его экземпляров.

SLON6.CC здесь еще больше. SLON--7.CC.

Рассмотрим принцип использование Null Object на примере. Предположим, что мы разрабатываем приложение для различных текстовых преобразований. Для этого определим следующий интерфейсный класс:

class TextConverter {
public:
    virtual ~TextConverter() { }
    virtual QString convert( const QString& text ) = 0;
};

Реализуем на основе этого интерфейса класс, который приводит все символы входного текста к верхнему регистру:

class UpperCaseTextConverter : public TextConverter {
public:
    QString convert( const QString& text ) {
        return text.toUpper();
    }
};

Без паттерна Null Object мы уже можем воспользоваться соответствующей функциональностью:

TextConverter* converter = NULL;

// … возможно, где-то вызывается converter = new UpperCaseTextConverter;

static const QString text = "Hello, world!";
if( converter )  {
    qDebug() << converter->convert( text );
}

// …

delete converter;

Однако обратите внимание на проверку перед вызовом функции convert(). Она необходима, поскольку указатель converter может указывать на NULL. Чтобы избежать этой проверки, применим Null Object:

class NullTextConverter : public TextConverter {
public:
    QString convert( const QString& text ) {
        // Ничего не делаем
        return text;
    }
};

Теперь осталось принять условное соглашение о том, что указатель TextConverter* изначально должен быть инициализирован не NULL, а экземпляром класса NullTextConverter (или каким-нибудь другим конкретным экземпляром):

TextConverter* converter = new NullTextConverter;

// … возможно, где-то вызывается converter = new UpperCaseTextConverter;

static const QString text = "Hello, world!";
// Можем смело вызывать, поскольку указатель всегда должен быть инициализирован:
qDebug() << converter->convert( text );

// …

delete converter;

Главное в этой ситуации - не забывать инициализировать указатель с помощью Null-объекта, иначе вы быстро запутаетесь и в вашем коде появятся ошибки.

Однако стоит признать, что этот паттерн больше подходит для тех языков программирования, где предусмотрена сборка мусора (например, Java). Но и на С++ его можно вполне успешно применять.

Таким образом, паттерн Null Object удачно дополняет архитектуру ООП-программ. А в сочетании с другими структурными решениями позволяет упростить код и существенно сократить число проверок.

Похожие публикации