#include <iostream>
#include <memory>
#include <vector>
/**
* Factory Method Pattern Example: Vehicle Factory
*
* - Product: Vehicle
* - ConcreteProduct: Car, Bike
* - Creator: VehicleFactory
* - ConcreteCreator: CarFactory, BikeFactory
*
* The factory method pattern defers object creation to subclasses. Clients create products
* through the factory base class interface without knowing the specific product type,
* achieving decoupling between creation logic and usage.
*/
// Product base class: Vehicle
class Vehicle {
public:
virtual ~Vehicle() = default;
virtual void drive() const = 0; // Product operation
};
// Concrete product: Car
class Car : public Vehicle {
public:
void drive() const override {
std::cout << "Driving a car 🚗" << std::endl;
}
};
// Concrete product: Bike
class Bike : public Vehicle {
public:
void drive() const override {
std::cout << "Riding a bike 🚲" << std::endl;
}
};
// Creator base class: declares the factory method
class VehicleFactory {
public:
virtual ~VehicleFactory() = default;
// Factory method: pure virtual, implemented by subclasses
virtual std::unique_ptr<Vehicle> createVehicle() const = 0;
// Method that uses the product (demonstrates factory method usage)
// This method defines steps for operating the product, but which product is created is determined by subclass
void useVehicle() const {
auto vehicle = createVehicle(); // Call factory method
vehicle->drive(); // Use product
}
};
// Concrete creator: produces cars
class CarFactory : public VehicleFactory {
public:
std::unique_ptr<Vehicle> createVehicle() const override {
return std::make_unique<Car>();
}
};
// Concrete creator: produces bikes
class BikeFactory : public VehicleFactory {
public:
std::unique_ptr<Vehicle> createVehicle() const override {
return std::make_unique<Bike>();
}
};
int main() {
std::cout << "=== Factory Method Pattern Demo ===" << std::endl;
// Using polymorphism: operate different factories through base class pointers/references
std::vector<std::unique_ptr<VehicleFactory>> factories;
factories.push_back(std::make_unique<CarFactory>());
factories.push_back(std::make_unique<BikeFactory>());
// Call useVehicle() through factory base class interface, internally calls factory method to create and use product
std::cout << "\nUsing products through factory base class interface:" << std::endl;
for (const auto& factory : factories) {
factory->useVehicle();
}
// Can also directly get product objects for more fine-grained operations
std::cout << "\nDirectly obtaining product objects:" << std::endl;
CarFactory carFactory;
auto car = carFactory.createVehicle(); // Get product object
car->drive(); // Use product
// Without smart pointers, traditional approach requires manual delete, but smart pointers are recommended
// This demonstrates factory method flexibility: even through factory base class reference, correct product can be created
std::cout << "\nCreating product through base class reference:" << std::endl;
VehicleFactory& factoryRef = carFactory;
auto anotherCar = factoryRef.createVehicle();
anotherCar->drive();
return 0;
}