Factory Method includes one create method to create one product type.

Create multiple product types? → Abstract Factory

Components

SOLID Principle

✅ Single Responsibility Principle (SRP)

✅ Open/Closed Principle (OCP)

✅ Liskov Substitution Principle (LSP) / Interface Segregation Principle (ISP)

✅ Dependency Inversion Principle (DIP)

OOP Langs Implementation

Inheritance

// Abstract Factory
abstract class ProductCreator {
	// Create method
  public abstract create(): Product;
  
  // Reusable Shared Logic
  protected shippingCost = 0;
  // @final
  public setShippingCost(cost: number) {
    this.shippingCost = cost;
  }
}

// Concrete Factory
class ProductCreatorA extends ProductCreator {
  public create(): Product {
	  // The product can either be encapsulated in the factory or use DI injection.
	  //  - Encapsulation: for fixed type cohesion and simplicity
	  //  - DI: for testability and runtime flexibility
    return new ProductA(this.shippingCost, 100);
  }
}

// Abstract Product
interface Product {
  totalCost(): string;
}
// Concrete Product
class ProductA implements Product {
  constructor(
		private shippingCost: number,
	  private basePrice: number) {}

  public totalCost(): void {
    const totalCost = this.basePrice + this.shippingCost;
    return `Total cost of the product: $${totalCost}`
  }
}

// Client
function compute(productCreator: ProductCreator) {
	productCreator.setShippingCost(15);
	let product = productCreator.create()
	product.totalCost()
}

compute(new ProductCreatorA());

Interface Polymorphism (Less Common)

Normally, the Reusable Shared Logic exists in Abstract Factory.

Polymorphism Decision

Go Implementation

Interface Polymorphism + Anonymous Composition (Not Idiomatic)