---
title: "Полтергейст (программирование)"
type: "antipattern"
slug: "poltergeist"
url: "http://localhost:3000/ru/antipatterns/poltergeist.md"
description: "Неуместный короткоживущий объект"
---
# Полтергейст (программирование)

> Неуместный короткоживущий объект

В [программировании](https://en.wikipedia.org/wiki/Computer%5Fprogramming "Computer programming") **полтергейст** (или **цыганская кибитка**) — это короткоживущий, обычно [не имеющий состояния](https://en.wikipedia.org/wiki/State%5F%28computer%5Fscience%29 "State (computer science)") объект, используемый для выполнения инициализации или для вызова методов в другом, более постоянном классе. Он считается [антипаттерном](https://en.wikipedia.org/wiki/Anti-pattern "Anti-pattern"). Исходное определение принадлежит Майклу Акройду, данное на конференции Object World West в 1996 году:

> Подобно тому как [цыганская кибитка](https://en.wikipedia.org/wiki/Vardo%5F%28Romani%5Fwagon%29 "Vardo (Romani wagon)") или [полтергейст](https://en.wikipedia.org/wiki/Poltergeist "Poltergeist") загадочно появляются и исчезают, так же ведёт себя и этот короткоживущий объект. Как следствие, код становится труднее сопровождать, и возникает излишний расход ресурсов. Типичная причина этого антипаттерна — плохой объектный дизайн.

Полтергейст часто можно опознать по его имени; в них нередко встречаются такие слова, как «Manager», «Controller», «Supervisor», «StartProcess» и т. п.

Иногда классы-полтергейсты создаются потому, что [программист](https://en.wikipedia.org/wiki/Programmer "Programmer") предвосхищал потребность в более сложной архитектуре. Например, полтергейст возникает, если один и тот же метод выступает одновременно и _клиентом_, и _инициатором_ в [паттерне «Команда»](https://en.wikipedia.org/wiki/Command%5Fpattern "Command pattern"), и программист предполагает разделить эти две фазы. Однако такая более сложная архитектура в действительности может так и не появиться.

Полтергейсты не следует путать с долгоживущими, несущими состояние объектами [паттернов](https://en.wikipedia.org/wiki/Software%5Fdesign%5Fpattern "Software design pattern"), таких как [модель—представление—контроллер](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller "Model–view–controller"), или паттернов, разделяющих уровни, таких как [паттерн «Бизнес-делегат»](https://en.wikipedia.org/wiki/Business%5Fdelegate%5Fpattern "Business delegate pattern").

Чтобы устранить полтергейст, удалите класс и перенесите его функциональность в вызываемый класс, возможно, посредством [наследования](https://en.wikipedia.org/wiki/Inheritance%5F%28object-oriented%5Fprogramming%29 "Inheritance (object-oriented programming)") или в виде [примеси (mixin)](https://en.wikipedia.org/wiki/Mixin "Mixin").

Были предложены методы обнаружения полтергейстов в коде для целей рефакторинга.

## Пример

Класс `Poltergeist` в этом примере на [C++](https://en.wikipedia.org/wiki/C%2B%2B "C++") можно рассматривать как «объект-полтергейст», поскольку он не добавляет дополнительной функциональности или инкапсуляции, а лишь увеличивает сложность за счёт ненужной абстракции.

import std;

using String = std::string;

// Класс-полтергейст, который просто хранит указатель, но не добавляет осмысленного поведения
class Poltergeist {
private:
    String* s; // указатель на строку, но сам класс не делает ничего полезного
public:
    explicit Poltergeist(String* s):
        s{s} {}

    ~Poltergeist() {
        delete s;
    }

    [[nodiscard]]
    String get() const noexcept {
        return s;
    }

    // Никакого дополнительного поведения или осмысленной функциональности
};

int main() {
    // Создаём объект Poltergeist, который просто хранит указатель на строку
    Poltergeist p(new String("Hello, world!"));

    // Просто передаёт данные дальше, не добавляя ценности
    std::println(*p.get());

    return 0;
}

Вместо этого правильнее было бы воспользоваться [умным указателем](https://en.wikipedia.org/wiki/Smart%5Fpointer "Smart pointer").

import std;

using String = std::string;
template <typename T>
using UniquePtr = std::unique_ptr<T>;

// Используем умные указатели напрямую для управления памятью
UniquePtr<String> s = std::make_unique<String>("Hello, World!");
std::println(*s);

Ещё один пример объекта-полтергейста / цыганской кибитки — следующий, где `UserCreator` создаётся лишь для выполнения нескольких простых действий.

import std;

using String = std::string;

class UserManager {
public:
    void createUser(const String& name) {
        std::println("User created: {}", name);
    }
};

// Класс-полтергейст
class UserCreator {
public:
    explicit UserCreator(const String& name) {
        UserManager manager;
        manager.createUser(name);
    }
};

int main() {
    // Создаём полтергейст лишь для того, чтобы вызвать createUser()
    UserCreator("Alice");
    UserCreator("Bob");
}

Это можно было бы более уместно сделать так, полностью избежав класса-полтергейста:

// Полностью избегаем полтергейста UserCreator
int main() {
    UserManager manager;
    manager.createUser("Alice");
    manager.createUser("Bob");
}
