Creational Patterns «Prev Next»

Lesson 6Factory Method: structure
ObjectiveDevelop the subclasses for the Vehicle Class.

Develop the Subclasses for the Vehicle Class

In the previous lesson and exercise, you defined an abstract Vehicle base class and enforced a key invariant: 0 ≤ speed ≤ maxSpeed. That base class is the “Product” abstraction in Factory Method terms—it defines a stable contract that all concrete vehicles must honor.

This lesson is about the next step: developing concrete subclasses (such as Car, Truck, or Bicycle) so client code can work with the abstract Vehicle type while the system decides which concrete vehicle to instantiate.

Why subclasses matter to Factory Method

Factory Method is most useful when you know you need some subclass of a base type, but you do not want to hard-code which one. In our running example:

When you create concrete subclasses correctly, you unlock these design benefits:

Factory Method structure

The classic GoF structure uses two abstract types above the “water line”:

Concrete implementations exist below the water line:

Diagram of Factory Method structure
Factory Method Structure (GoF)

Product (abstract)
  • Role: Defines the interface for objects the factory method creates.
  • Type: Abstract class or interface
  • Responsibility: Declares the common behavior for all products.
ConcreteProduct
  • Role: Implements the Product interface.
  • Type: Concrete class
  • Relationship: Inherits from Product
  • Responsibility: Provides a specific implementation of the product.
Creator (abstract)
  • Role: Declares the factory method.
  • Type: Abstract class
  • Method:
factoryMethod() : Product
  • Responsibility: Defines the factory method that returns a Product.
  • May contain business logic that relies on products, without knowing their concrete types.
ConcreteCreator
  • Role: Implements the factory method.
  • Type: Concrete class
  • Relationship: Inherits from Creator
  • Responsibility: Instantiates and returns a specific ConcreteProduct.
Conceptual Summary
  • The Creator defines what is created (a Product),
  • while the ConcreteCreator decides which concrete class to instantiate.

Clients typically depend only on the two abstract types “above the water line.” Many concrete products and creators can exist below the line, but client code never needs to reference them directly.

Applying the structure to Vehicle subclasses

In this module’s vehicle example:

Your task in this lesson is to build the ConcreteProduct layer: the subclasses that extend Vehicle and provide any additional behavior or identifying information required by the exercise (for example, a concrete getType() in C++, or a useful toString() / type label in Java).

Parameterized Factory Method

A common variation is the parameterized Factory Method. Instead of an abstract creator hierarchy, you have a single creator method that takes a parameter and decides which product subclass to instantiate based on the argument.

This design appears frequently in modern APIs because it centralizes creation logic in one place. A classic Java example is java.net.URL.openConnection(), which returns a URLConnection whose concrete type depends on the URL scheme.

Diagram of the Factory Method using parameterized Factory Method
Parameterized Factory Method Structure

Product (abstract)
  • Type: Abstract class or interface
  • Purpose: Defines the abstract product interface.
ConcreteProduct
  • Type: Concrete class
  • Relationship: Extends Product
  • Purpose: Implements the abstract Product.
ConcreteCreator
  • Type: Concrete class
  • Method: factoryMethod(parameter) : Product
  • Purpose: Creates and returns a ConcreteProduct, while exposing the return type as Product.
Key Structural Observation
  • There is no abstract Creator class in this variation.
  • Object creation is still abstracted by returning Product.
  • Variation is controlled by a parameter instead of subclassing the creator.

Modern design note

In modern codebases, you’ll often see Factory Method concepts expressed through dependency injection, provider registries, or service discovery mechanisms. Even then, the design goal is the same: keep client code stable by returning abstractions, not concrete classes.

If you later combine this pattern with techniques like configuration files, environment variables, or feature flags, you can select which Vehicle subclass to create at runtime without changing or recompiling client code.

Concrete Subclasses - Exercise

In this exercise, you will write four subclasses for the Vehicle class.
Concrete Subclasses - Exercise

SEMrush Software 5 SEMrush Banner 5