In computer programming, a poltergeist (or gypsy wagon) is a short-lived, typically stateless object used to perform initialization or to invoke methods in another, more permanent class. It is considered an anti-pattern. The original definition is by Michael Akroyd at the 1996 Object World West Conference:

A poltergeist can often be identified by its name; they often include words such as "", "", "", "", etc. in the name.

Sometimes, poltergeist classes are created because the programmer anticipated the need for a more complex architecture. For example, a poltergeist arises if the same method acts as both the client and invoker in a command pattern, and the programmer anticipates separating the two phases. However, this more complex architecture may actually never materialize.

Poltergeists should not be confused with long-lived, state-bearing objects of a pattern such as model–view–controller, or tier-separating patterns such as business delegate pattern.

To remove a poltergeist, delete the class and insert its functionality in the invoked class, possibly by inheritance or as a mixin.

There have been proposed methods in detecting poltergeists in code for refactoring.

Example

This <code>Poltergeist</code> class in this C++ example can be seen as a "poltergeist object", due to not adding additional functionality or encapsulation and only increasing complexity with unnecessary abstraction.

<syntaxhighlight lang="cpp">

import std;

using String = std::string;

// Poltergeist class that just holds a pointer, but adds no meaningful behavior

class Poltergeist {

private:

String* s; // pointer to string, but the class itself doesn't do anything useful

public:

explicit Poltergeist(String* s):

s{s} {}

~Poltergeist() {

delete s;

}

nodiscard

String get() const noexcept {

return s;

}

// No additional behavior or meaningful functionality

};

int main() {

// Create a Poltergeist object that just holds a pointer to the string

Poltergeist p(new String("Hello, world!"));

// Just passes the data around without adding value

std::println(*p.get());

return 0;

}

</syntaxhighlight>

This could instead be more appropriately done using a smart pointer.

<syntaxhighlight lang="cpp">

import std;

using String = std::string;

template <typename T>

using UniquePtr = std::unique_ptr<T>;

// Use smart pointers directly to manage memory

UniquePtr<String> s = std::make_unique<String>("Hello, World!");

std::println(*s);

</syntaxhighlight>

Another example of a poltergeist/gypsy wagon object, is the following, where <code>UserCreator</code> is instantiated just to perform some basic actions.

<syntaxhighlight lang="cpp">

import std;

using String = std::string;

class UserManager {

public:

void createUser(const String& name) {

std::println("User created: {}", name);

}

};

// The poltergeist class

class UserCreator {

public:

explicit UserCreator(const String& name) {

UserManager manager;

manager.createUser(name);

}

};

int main() {

// Creating a poltergeist just to call createUser()

UserCreator("Alice");

UserCreator("Bob");

}

</syntaxhighlight>

This could be more appropriately done like so, avoiding any poltergeist class entirely:

<syntaxhighlight lang="cpp">

// Avoid the UserCreator poltergeist entirely

int main() {

UserManager manager;

manager.createUser("Alice");

manager.createUser("Bob");

}

</syntaxhighlight>

See also

  • Anti-pattern
  • Factory (object-oriented programming)
  • YAGNI principle

References