← All Patterns
creational4 participants

Factory Method

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

The Problem

Your framework needs to create objects, but it should not be hardcoded to specific classes. The framework knows when to create, but not what to create. Subclasses or configurations should control what gets built.

Structure

«abstract»Creatormake_lexer() →CParserFactorymake_lexer() →CLexerVerilogFactorymake_lexer() →VerilogLexerCLexer : LexerVLexer : Lexer

Execution Walkthrough

1

Product interface

Define a Product interface (e.g. Lexer) that all concrete products must implement.

2

Creator declares

3

Subclass overrides

4

Client uses Creator

5

Open/Closed

Code Comparison

Client directly instantiates — hardcoded to concrete types. Adding a language means modifying client code.

// BAD: client picks concrete type explicitly
void run_parser(std::string lang) {
  if (lang == "C") {
    CLexer lexer;
    CParser parser(lexer);
    parser.parse();
  } else if (lang == "verilog") {
    VerilogLexer lexer;
    VerilogParser parser(lexer);
    parser.parse();
  }
  // Adding SystemVerilog? Modify this function.
}

Full C++ Implementation

C++ · Factory Method
#include <memory>
#include <string>
#include <iostream>

struct Token {
  enum Type { INT, FLOAT, IDENT, EOF_ } type;
  std::string val;
};

struct Lexer {
  virtual std::unique_ptr<Token> next_token() = 0;
  virtual ~Lexer() = default;
};

struct CLexer : Lexer {
  bool done_ = false;
  std::unique_ptr<Token> next_token() override {
    if (done_) return std::make_unique<Token>(Token::EOF_, "");
    done_ = true;
    return std::make_unique<Token>(Token::IDENT, "int_var");
  }
};

struct VerilogLexer : Lexer {
  bool done_ = false;
  std::unique_ptr<Token> next_token() override {
    if (done_) return std::make_unique<Token>(Token::EOF_, "");
    done_ = true;
    return std::make_unique<Token>(Token::IDENT, "clk");
  }
};

struct ParserFactory {
  virtual std::unique_ptr<Lexer> make_lexer() = 0;
  void run() {
    auto lex = make_lexer();
    auto tok = lex->next_token();
    std::cout << "token: " << tok->val << "\n";
  }
};

struct CParserFactory : ParserFactory {
  std::unique_ptr<Lexer> make_lexer() override {
    return std::make_unique<CLexer>();
  }
};

struct VerilogFactory : ParserFactory {
  std::unique_ptr<Lexer> make_lexer() override {
    return std::make_unique<VerilogLexer>();
  }
};

int main() {
  std::unique_ptr<ParserFactory> f = std::make_unique<VerilogFactory>();
  f->run();   // prints: token: clk
}

Participants

CreatorConcreteCreatorProductConcreteProduct

Where it is used

Compiler front-ends

A parser factory creates Lexer, Parser, or ASTBuilder depending on the input language dialect.

LLVM

IRBuilder::Create* are factory methods producing typed IR instruction nodes for the current basic block.

Database drivers

DriverManager::getConnection() returns MySQLConnection or PostgresConnection based on the JDBC URL.

UI toolkits

Cross-platform widget factory creates WinButton on Windows and GTKButton on Linux — same call site.

CommandBuilder