Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Factory pattern

Use case

Create architecture-specific disassembler without hardcoding which class to instantiate.

Explanation

Factory encapsulates object creation logic. Client code works with abstract interface while concrete types are selected at runtime. Modern C++ uses std::unique_ptr for ownership.

Code

#include <cstdint>
#include <memory>
#include <print>
#include <string>

class Disassembler {
public:
  virtual ~Disassembler() = default;
  virtual std::string name() const = 0;
};

class X64Disassembler : public Disassembler {
public:
  std::string name() const override { return "x86-64"; }
};

class ARM64Disassembler : public Disassembler {
public:
  std::string name() const override { return "arm64"; }
};

std::unique_ptr<Disassembler> create_disassembler(const std::string &arch) {
  if (arch == "x86-64") {
    return std::make_unique<X64Disassembler>();
  }
  if (arch == "arm64") {
    return std::make_unique<ARM64Disassembler>();
  }
  return nullptr;
}

int main() {
  for (auto arch : {"x86-64", "arm64", "mips"}) {
    if (auto disasm = create_disassembler(arch)) {
      std::println("{}", disasm->name());
    } else {
      std::println("Not supported: {}", arch);
    }
  }
  return 0;
}

View on GitHub.

Output

$ ./src/design-patterns-and-idioms/build/factory-pattern
x86-64
arm64
Not supported: mips