Abstract Factory
The Abstract Factory pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It allows a system to be independent of how its products are created, composed, and represented. Effectively, it’s a “factory of factories”—a way to delegate the responsibility of object creation to other objects.
This pattern is particularly useful when you need to create different combinations of related objects that depend on a configuration or platform. It promotes loose coupling between classes and makes it easy to switch between different “looks and feels” or object implementations without modifying the client code. It addresses the issue of creating multiple coupled object families when a simple factory isn’t flexible enough.
Usage
The Abstract Factory pattern is commonly used in these scenarios:
- GUI Frameworks: Creating widgets (buttons, text fields, etc.) that are specific to a particular operating system (Windows, macOS, Linux). Each OS needs a distinct set of widgets.
- Database Abstraction: Providing an abstraction layer for different database systems (MySQL, PostgreSQL, Oracle). An abstract factory can create database connections, queries, and commands.
- Configuration Management: Dynamically loading and configuring different sets of components based on a configuration file or environment variable.
- Cross-Platform Development: Where the same high-level code needs to interact with platform-specific implementations.
Examples
-
Java Swing/JFace: Java’s Swing and Eclipse’s JFace frameworks utilize abstract factories extensively. They provide different “look and feel” factories that allow applications to easily adapt to different operating systems and user preferences. Each factory creates a complete set of UI components—buttons, text fields, scrollbars, etc.—that share a consistent style.
-
Spring Framework (Bean Definition Factories): Spring’s configuration mechanism uses an abstract factory approach. While not directly named as such, the
BeanFactory(and its implementations likeXmlBeanFactoryorAnnotationConfigBeanFactory) effectively act as abstract factories for creating and managing beans within the application context. DifferentBeanFactoryimplementations use differing sources for bean definitions (XML, annotations, Java config) but provide a consistent interface for retrieving beans. -
Unity Game Engine: Unity’s Asset Serialization system can leverage Abstract Factories. Different asset formats (e.g., FBX, OBJ, custom formats) can have different serialization/deserialization methods. An abstract factory could be used to provide a common interface for creating asset importers and exporters tailored to specific asset types without the core engine needing to know the details of each format.
Specimens
15 implementationsThe Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a creational pattern that promotes loose coupling and allows for easy switching between different “themes” or variations of objects.
This Dart implementation defines an AbstractFactory interface with a method to create a ProductA and a ProductB. Concrete factories, like ConcreteFactory1 and ConcreteFactory2, implement this interface to produce specific variations of these products. A Client class then uses the factory interface to obtain objects without knowing their concrete types. This adheres to Dart’s preference for interfaces and abstract classes for defining contracts, and utilizes constructor injection for dependency management, making the code testable and maintainable.
abstract class ProductA {
void interact(ProductB b);
}
abstract class ProductB {
void interact(ProductA a);
}
abstract class AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
class ConcreteProductA1 implements ProductA {
@override
void interact(ProductB b) {
print('ConcreteProductA1 interacts with ProductB');
b.interact(this);
}
}
class ConcreteProductB1 implements ProductB {
@override
void interact(ProductA a) {
print('ConcreteProductB1 interacts with ProductA');
}
}
class ConcreteProductA2 implements ProductA {
@override
void interact(ProductB b) {
print('ConcreteProductA2 interacts with ProductB');
b.interact(this);
}
}
class ConcreteProductB2 implements ProductB {
@override
void interact(ProductA a) {
print('ConcreteProductB2 interacts with ProductA');
}
}
class ConcreteFactory1 implements AbstractFactory {
@override
ProductA createProductA() {
return ConcreteProductA1();
}
@override
ProductB createProductB() {
return ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
@override
ProductA createProductA() {
return ConcreteProductA2();
}
@override
ProductB createProductB() {
return ConcreteProductB2();
}
}
class Client {
final AbstractFactory factory;
Client(this.factory);
void run() {
final productA = factory.createProductA();
final productB = factory.createProductB();
productA.interact(productB);
}
}
void main() {
final factory1 = ConcreteFactory1();
final client1 = Client(factory1);
client1.run();
final factory2 = ConcreteFactory2();
final client2 = Client(factory2);
client2.run();
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “looks and feels” or object sets easily.
This Scala implementation defines traits Button and Checkbox representing product types, and concrete classes for different themes (e.g., WindowsButton, MacOSCheckbox). The GUIFactory trait is the abstract factory, defining methods to create buttons and checkboxes. Concrete factories like WindowsFactory and MacOSFactory implement these methods to return objects specific to their theme. A Client class uses the factory to create a GUI without knowing the concrete classes involved, promoting loose coupling and flexibility. Scala’s traits and case classes make this pattern concise and type-safe.
trait Button {
def paint(): String
}
trait Checkbox {
def paint(): String
}
trait GUIFactory {
def createButton(): Button
def createCheckbox(): Checkbox
}
case class WindowsButton() extends Button {
override def paint(): String = "Windows Button"
}
case class MacOSButton() extends Button {
override def paint(): String = "MacOS Button"
}
case class WindowsCheckbox() extends Checkbox {
override def paint(): String = "Windows Checkbox"
}
case class MacOSCheckbox() extends Checkbox {
override def paint(): String = "MacOS Checkbox"
}
case class WindowsFactory() extends GUIFactory {
override def createButton(): Button = WindowsButton()
override def createCheckbox(): Checkbox = WindowsCheckbox()
}
case class MacOSFactory() extends GUIFactory {
override def createButton(): Button = MacOSButton()
override def createCheckbox(): Checkbox = MacOSCheckbox()
}
object Client {
def createGUI(factory: GUIFactory): String = {
val button = factory.createButton()
val checkbox = factory.createCheckbox()
s"${button.paint()}, ${checkbox.paint()}"
}
}
object Main extends App {
val windowsGUI = Client.createGUI(WindowsFactory())
println(windowsGUI)
val macosGUI = Client.createGUI(MacOSFactory())
println(macosGUI)
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “themes” or configurations of objects easily.
This PHP example defines abstract classes for Button and Checkbox (the products) and an abstract GUIFactory (the abstract factory). Concrete factories, WindowsGUIFactory and WebGUIFactory, implement the GUIFactory to create platform-specific buttons and checkboxes. The Application class uses a factory to create a complete GUI, demonstrating how to decouple the client code from the concrete widget classes. This approach is idiomatic PHP due to its reliance on interfaces and abstract classes for achieving loose coupling and extensibility, common practices in larger PHP projects.
<?php
// Abstract Products
abstract class Button {
abstract public function render(): string;
}
abstract class Checkbox {
abstract public function render(): string;
}
// Concrete Products (Windows)
class WindowsButton extends Button {
public function render(): string {
return '<button>Windows Button</button>';
}
}
class WindowsCheckbox extends Checkbox {
public function render(): string {
return '<input type="checkbox" value="Windows Checkbox">';
}
}
// Concrete Products (Web)
class WebButton extends Button {
public function render(): string {
return '<button>Web Button</button>';
}
}
class WebCheckbox extends Checkbox {
public function render(): string {
return '<input type="checkbox" value="Web Checkbox">';
}
}
// Abstract Factory
abstract class GUIFactory {
abstract public function createButton(): Button;
abstract public function createCheckbox(): Checkbox;
}
// Concrete Factories
class WindowsGUIFactory extends GUIFactory {
public function createButton(): Button {
return new WindowsButton();
}
public function createCheckbox(): Checkbox {
return new WindowsCheckbox();
}
}
class WebGUIFactory extends GUIFactory {
public function createButton(): Button {
return new WebButton();
}
public function createCheckbox(): Checkbox {
return new WebCheckbox();
}
}
// Client
class Application {
private GUIFactory $factory;
public function __construct(GUIFactory $factory) {
$this->factory = $factory;
}
public function createGUI(): void {
$button = $this->factory->createButton();
$checkbox = $this->factory->createCheckbox();
echo $button->render();
echo $checkbox->render();
}
}
// Usage
$windowsFactory = new WindowsGUIFactory();
$appWindows = new Application($windowsFactory);
$appWindows->createGUI();
$webFactory = new WebGUIFactory();
$appWeb = new Application($webFactory);
$appWeb->createGUI();
?>
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s useful when you need to create different “flavors” of objects that work together, and you want to decouple the client code from the specific implementations.
This Ruby implementation defines an AbstractFactory with a method for each product type. Concrete factories (ConcreteFactory1, ConcreteFactory2) implement this interface to produce specific product families (ProductA1, ProductB1 vs. ProductA2, ProductB2). The client code interacts with the factory interface, not the concrete factories, promoting loose coupling and allowing for easy addition of new product families. Ruby’s duck typing and flexible method definitions make this pattern a natural fit.
# Abstract Factory
class AbstractFactory
def create_product_a
raise NotImplementedError
end
def create_product_b
raise NotImplementedError
end
end
# Concrete Factory 1
class ConcreteFactory1 < AbstractFactory
def create_product_a
ProductA1.new
end
def create_product_b
ProductB1.new
end
end
# Concrete Factory 2
class ConcreteFactory2 < AbstractFactory
def create_product_a
ProductA2.new
end
def create_product_b
ProductB2.new
end
end
# Products
class ProductA1
def operation_a
"Product A1 operation"
end
end
class ProductA2
def operation_a
"Product A2 operation"
end
end
class ProductB1
def operation_b
"Product B1 operation"
end
end
class ProductB2
def operation_b
"Product B2 operation"
end
end
# Client Code
factory1 = ConcreteFactory1.new
product_a1 = factory1.create_product_a
product_b1 = factory1.create_product_b
puts product_a1.operation_a
puts product_b1.operation_b
factory2 = ConcreteFactory2.new
product_a2 = factory2.create_product_a
product_b2 = factory2.create_product_b
puts product_a2.operation_a
puts product_b2.operation_b
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a creational pattern that promotes loose coupling and allows for easy switching between different “look and feels” or object sets.
The Swift code defines a VehicleFactory protocol with a method to create a Vehicle. Concrete factories, FordFactory and ToyotaFactory, implement this protocol, each producing specific vehicle types (e.g., FordFocus, ToyotaCorolla). A Vehicle protocol defines common behavior, and concrete vehicles implement it. The client code requests vehicles through the factory interface, decoupling it from the concrete vehicle classes. This implementation leverages Swift’s protocols for defining interfaces and utilizes concrete types for the factory and product implementations, aligning with Swift’s emphasis on type safety and clarity.
// Vehicle Protocol
protocol Vehicle {
func drive()
}
// Concrete Vehicles
struct FordFocus: Vehicle {
func drive() {
print("Driving a Ford Focus")
}
}
struct ToyotaCorolla: Vehicle {
func drive() {
print("Driving a Toyota Corolla")
}
}
// Abstract Factory Protocol
protocol VehicleFactory {
func createVehicle() -> Vehicle
}
// Concrete Factories
struct FordFactory: VehicleFactory {
func createVehicle() -> Vehicle {
return FordFocus()
}
}
struct ToyotaFactory: VehicleFactory {
func createVehicle() -> Vehicle {
return ToyotaCorolla()
}
}
// Client Code
func clientCode(factory: VehicleFactory) {
let vehicle = factory.createVehicle()
vehicle.drive()
}
// Usage
let fordFactory = FordFactory()
clientCode(factory: fordFactory)
let toyotaFactory = ToyotaFactory()
clientCode(factory: toyotaFactory)
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “look and feels” or configurations easily.
This Kotlin example defines an AbstractFactory interface with a method to create a Button and a TextField. Concrete factories, WindowsFactory and MacOSFactory, implement this interface, returning Windows-specific or macOS-specific UI elements respectively. A Client class uses the factory to create UI components without knowing their concrete types. This implementation leverages Kotlin’s interfaces and classes for a clean, type-safe approach, fitting its object-oriented nature. The use of object for the concrete factories demonstrates Kotlin’s preference for singletons when appropriate.
// Abstract Factory Interface
interface AbstractFactory {
fun createButton(): Button
fun createTextField(): TextField
}
// Abstract Product Interfaces
interface Button {
fun paint()
}
interface TextField {
fun display()
}
// Concrete Products - Windows
class WindowsButton : Button {
override fun paint() {
println("Painting a Windows button")
}
}
class WindowsTextField : TextField {
override fun display() {
println("Displaying a Windows text field")
}
}
// Concrete Products - macOS
class MacOSButton : Button {
override fun paint() {
println("Painting a macOS button")
}
}
class MacOSTextField : TextField {
override fun display() {
println("Displaying a macOS text field")
}
}
// Concrete Factories
object WindowsFactory : AbstractFactory {
override fun createButton(): Button = WindowsButton()
override fun createTextField(): TextField = WindowsTextField()
}
object MacOSFactory : AbstractFactory {
override fun createButton(): Button = MacOSButton()
override fun createTextField(): TextField = MacOSTextField()
}
// Client
class Client(factory: AbstractFactory) {
private val button: Button = factory.createButton()
private val textField: TextField = factory.createTextField()
fun render() {
button.paint()
textField.display()
}
}
// Usage
fun main() {
println("Using Windows Factory:")
Client(WindowsFactory).render()
println("\nUsing macOS Factory:")
Client(MacOSFactory).render()
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a creational pattern that promotes loose coupling and allows for easy switching between different “themes” or variations of objects.
This Rust implementation defines traits Chair and Table representing product families. FurnitureFactory is the abstract factory trait with a method to create both a Chair and a Table. Concrete factories, ModernFurnitureFactory and VintageFurnitureFactory, implement this trait, providing specific implementations for each product. The client code interacts with the factory interface, not the concrete classes, enabling flexibility and maintainability. Rust’s traits and ownership system naturally support this pattern, promoting compile-time safety and clear interfaces.
// Define product families
trait Chair {
fn sit(&self);
}
trait Table {
fn place_on(&self);
}
// Concrete products for Modern furniture
struct ModernChair;
impl Chair for ModernChair {
fn sit(&self) {
println!("Sitting on a modern chair.");
}
}
struct ModernTable;
impl Table for ModernTable {
fn place_on(&self) {
println!("Placing items on a modern table.");
}
}
// Concrete products for Vintage furniture
struct VintageChair;
impl Chair for VintageChair {
fn sit(&self) {
println!("Sitting on a vintage chair.");
}
}
struct VintageTable;
impl Table for VintageTable {
fn place_on(&self) {
println!("Placing items on a vintage table.");
}
}
// Abstract Factory
trait FurnitureFactory {
fn create_chair(&self) -> Box<dyn Chair>;
fn create_table(&self) -> Box<dyn Table>;
}
// Concrete Factory for Modern furniture
struct ModernFurnitureFactory;
impl FurnitureFactory for ModernFurnitureFactory {
fn create_chair(&self) -> Box<dyn Chair> {
Box::new(ModernChair)
}
fn create_table(&self) -> Box<dyn Table> {
Box::new(ModernTable)
}
}
// Concrete Factory for Vintage furniture
struct VintageFurnitureFactory;
impl FurnitureFactory for VintageFurnitureFactory {
fn create_chair(&self) -> Box<dyn Chair> {
Box::new(VintageChair)
}
fn create_table(&self) -> Box<dyn Table> {
Box::new(VintageTable)
}
}
fn main() {
// Client code
let modern_factory = ModernFurnitureFactory;
let modern_chair = modern_factory.create_chair();
let modern_table = modern_factory.create_table();
modern_chair.sit();
modern_table.place_on();
let vintage_factory = VintageFurnitureFactory;
let vintage_chair = vintage_factory.create_chair();
let vintage_table = vintage_factory.create_table();
vintage_chair.sit();
vintage_table.place_on();
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “looks and feels” or configurations of objects easily.
This Go implementation defines interfaces for Chair, Table, and Factory. Concrete types like ModernChair, ModernTable, ArtDecoChair, and ArtDecoTable implement the product interfaces. ModernFurnitureFactory and ArtDecoFurnitureFactory implement the Factory interface, each responsible for creating a complete set of furniture in its style. The client code interacts with the factory interface, not the concrete classes, promoting loose coupling and flexibility. Go’s interfaces make this pattern a natural fit, as they define behavior without dictating implementation.
// Chair interface represents a chair.
type Chair interface {
Sit() string
}
// Table interface represents a table.
type Table interface {
Use() string
}
// Factory interface represents the abstract factory.
type Factory interface {
CreateChair() Chair
CreateTable() Table
}
// ModernChair is a concrete chair.
type ModernChair struct{}
func (c *ModernChair) Sit() string {
return "Sitting on a modern chair."
}
// ModernTable is a concrete table.
type ModernTable struct{}
func (t *ModernTable) Use() string {
return "Using a modern table."
}
// ArtDecoChair is a concrete chair.
type ArtDecoChair struct{}
func (c *ArtDecoChair) Sit() string {
return "Sitting on an Art Deco chair."
}
// ArtDecoTable is a concrete table.
type ArtDecoTable struct{}
func (t *ArtDecoTable) Use() string {
return "Using an Art Deco table."
}
// ModernFurnitureFactory creates modern furniture.
type ModernFurnitureFactory struct{}
func (f *ModernFurnitureFactory) CreateChair() Chair {
return &ModernChair{}
}
func (f *ModernFurnitureFactory) CreateTable() Table {
return &ModernTable{}
}
// ArtDecoFurnitureFactory creates Art Deco furniture.
type ArtDecoFurnitureFactory struct{}
func (f *ArtDecoFurnitureFactory) CreateChair() Chair {
return &ArtDecoChair{}
}
func (f *ArtDecoFurnitureFactory) CreateTable() Table {
return &ArtDecoTable{}
}
// Client code
func main() {
var factory Factory
// Create modern furniture
factory = &ModernFurnitureFactory{}
chair := factory.CreateChair()
table := factory.CreateTable()
println(chair.Sit())
println(table.Use())
// Create Art Deco furniture
factory = &ArtDecoFurnitureFactory{}
chair = factory.CreateChair()
table = factory.CreateTable()
println(chair.Sit())
println(table.Use())
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “looks and feels” or object sets easily. This example demonstrates creating different types of buttons (Windows and HTML) and text boxes using an abstract factory. The Factory struct defines the abstract factory interface, and concrete factories (WindowsFactory, HTMLFactory) implement it to produce specific button and textbox types. C’s struct-based approach naturally lends itself to defining interfaces and concrete implementations, fitting the pattern’s intent.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Abstract Products
typedef struct Button Button;
typedef struct TextBox TextBox;
// Abstract Factory
typedef struct Factory Factory;
// Concrete Products - Windows
typedef struct WindowsButton WindowsButton;
typedef struct WindowsTextBox WindowsTextBox;
// Concrete Products - HTML
typedef struct HTMLButton HTMLButton;
typedef struct HTMLTextBox HTMLTextBox;
// Button Interface
struct Button {
void (*paint)(Button* this);
};
// TextBox Interface
struct TextBox {
void (*render)(TextBox* this);
};
// Windows Button
struct WindowsButton {
Button base;
char* text;
};
void windowsButtonPaint(Button* this) {
WindowsButton* winButton = (WindowsButton*)this;
printf("Windows Button: %s\n", winButton->text);
}
// HTML Button
struct HTMLButton {
Button base;
char* text;
};
void htmlButtonPaint(Button* this) {
HTMLButton* htmlButton = (HTMLButton*)this;
printf("<button>%s</button>\n", htmlButton->text);
}
// Windows TextBox
struct WindowsTextBox {
TextBox base;
int width;
int height;
};
void windowsTextBoxRender(TextBox* this) {
WindowsTextBox* winTextBox = (WindowsTextBox*)this;
printf("Windows TextBox (width=%d, height=%d)\n", winTextBox->width, winTextBox->height);
}
// HTML TextBox
struct HTMLTextBox {
TextBox base;
int width;
int height;
};
void htmlTextBoxRender(TextBox* this) {
HTMLTextBox* htmlTextBox = (HTMLTextBox*)this;
printf("<textarea width=%d height=%d></textarea>\n", htmlTextBox->width, htmlTextBox->height);
}
// Abstract Factory Interface
struct Factory {
Button* (*createButton)(char* text);
TextBox* (*createTextBox)(int width, int height);
};
// Concrete Factory - Windows
typedef struct WindowsFactory WindowsFactory;
struct WindowsFactory {
Factory base;
};
Button* windowsFactoryCreateButton(char* text) {
WindowsButton* button = (WindowsButton*)malloc(sizeof(WindowsButton));
button->base.paint = windowsButtonPaint;
button->text = strdup(text); // Duplicate the string to avoid dangling pointers
return (Button*)button;
}
TextBox* windowsFactoryCreateTextBox(int width, int height) {
WindowsTextBox* textBox = (WindowsTextBox*)malloc(sizeof(WindowsTextBox));
textBox->base.render = windowsTextBoxRender;
textBox->width = width;
textBox->height = height;
return (TextBox*)textBox;
}
// Concrete Factory - HTML
typedef struct HTMLFactory HTMLFactory;
struct HTMLFactory {
Factory base;
};
Button* htmlFactoryCreateButton(char* text) {
HTMLButton* button = (HTMLButton*)malloc(sizeof(HTMLButton));
button->base.paint = htmlButtonPaint;
button->text = strdup(text);
return (Button*)button;
}
TextBox* htmlFactoryCreateTextBox(int width, int height) {
HTMLTextBox* textBox = (HTMLTextBox*)malloc(sizeof(HTMLTextBox));
textBox->base.render = htmlTextBoxRender;
textBox->width = width;
textBox->height = height;
return (TextBox*)textBox;
}
// Client Code
int main() {
WindowsFactory windowsFactory;
windowsFactory.base.createButton = windowsFactoryCreateButton;
windowsFactory.base.createTextBox = windowsFactoryCreateTextBox;
HTMLFactory htmlFactory;
htmlFactory.base.createButton = htmlFactoryCreateButton;
htmlFactory.base.createTextBox = htmlFactoryCreateTextBox;
// Create Windows elements
Button* windowsButton = windowsFactory.base.createButton("Click Me");
windowsButton->base.paint(windowsButton);
TextBox* windowsTextBox = windowsFactory.base.createTextBox(100, 20);
windowsTextBox->base.render(windowsTextBox);
// Create HTML elements
Button* htmlButton = htmlFactory.base.createButton("Submit");
htmlButton->base.paint(htmlButton);
TextBox* htmlTextBox = htmlFactory.base.createTextBox(50, 10);
htmlTextBox->base.render(htmlTextBox);
free(windowsButton);
free(htmlTextBox);
free(htmlButton);
free(htmlTextBox);
return 0;
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “looks and feels” or object configurations easily.
This C++ example defines abstract classes Button and Checkbox representing product types, and concrete classes WindowsButton and MacOSButton (and similar for Checkbox) as their implementations. AbstractFactory declares methods to create these products. WindowsFactory and MacOSFactory implement the factory, returning Windows/MacOS specific objects. The client code uses the factory interface to create UI elements, decoupling it from concrete classes. This implementation uses pure virtual functions to enforce the abstract nature and demonstrates a common C++ approach to polymorphism through inheritance.
#include <iostream>
// Abstract Products
class Button {
public:
virtual void paint() = 0;
};
class Checkbox {
public:
virtual void paint() = 0;
};
// Concrete Products - Windows
class WindowsButton : public Button {
public:
void paint() override {
std::cout << "Painting a Windows Button" << std::endl;
}
};
class WindowsCheckbox : public Checkbox {
public:
void paint() override {
std::cout << "Painting a Windows Checkbox" << std::endl;
}
};
// Concrete Products - macOS
class MacOSButton : public Button {
public:
void paint() override {
std::cout << "Painting a macOS Button" << std::endl;
}
};
class MacOSCheckbox : public Checkbox {
public:
void paint() override {
std::cout << "Painting a macOS Checkbox" << std::endl;
}
};
// Abstract Factory
class AbstractFactory {
public:
virtual Button* createButton() = 0;
virtual Checkbox* createCheckbox() = 0;
virtual ~AbstractFactory() = default;
};
// Concrete Factories
class WindowsFactory : public AbstractFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
Checkbox* createCheckbox() override {
return new WindowsCheckbox();
}
};
class MacOSFactory : public AbstractFactory {
public:
Button* createButton() override {
return new MacOSButton();
}
Checkbox* createCheckbox() override {
return new MacOSCheckbox();
}
};
// Client Code
void clientCode(AbstractFactory* factory) {
Button* button = factory->createButton();
Checkbox* checkbox = factory->createCheckbox();
button->paint();
checkbox->paint();
delete button;
delete checkbox;
}
int main() {
WindowsFactory* windowsFactory = new WindowsFactory();
clientCode(windowsFactory);
MacOSFactory* macOsFactory = new MacOSFactory();
clientCode(macOsFactory);
delete windowsFactory;
delete macOsFactory;
return 0;
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It promotes loose coupling and allows for easy switching between different “themes” or configurations of objects.
This C# example defines abstract classes for Chair, Table, and Factory (the Abstract Factory). Concrete classes ModernChair, ModernTable, and ModernFurnitureFactory implement the modern furniture theme. Similarly, VictorianChair, VictorianTable, and VictorianFurnitureFactory implement the Victorian theme. A client can request a furniture set (chair and table) through the factory interface without knowing the specifics of the concrete classes. This adheres to C#’s interface-based programming and promotes extensibility through new factory and product implementations.
// Abstract Products
public abstract class Chair
{
public abstract void SitOn();
}
public abstract class Table
{
public abstract void PlaceOn();
}
// Abstract Factory
public abstract class FurnitureFactory
{
public abstract Chair CreateChair();
public abstract Table CreateTable();
}
// Concrete Products (Modern)
public class ModernChair : Chair
{
public override void SitOn()
{
Console.WriteLine("Sitting on a modern chair.");
}
}
public class ModernTable : Table
{
public override void PlaceOn()
{
Console.WriteLine("Placing items on a modern table.");
}
}
// Concrete Factory (Modern)
public class ModernFurnitureFactory : FurnitureFactory
{
public override Chair CreateChair()
{
return new ModernChair();
}
public override Table CreateTable()
{
return new ModernTable();
}
}
// Concrete Products (Victorian)
public class VictorianChair : Chair
{
public override void SitOn()
{
Console.WriteLine("Sitting on a Victorian chair.");
}
}
public class VictorianTable : Table
{
public override void PlaceOn()
{
Console.WriteLine("Placing items on a Victorian table.");
}
}
// Concrete Factory (Victorian)
public class VictorianFurnitureFactory : FurnitureFactory
{
public override Chair CreateChair()
{
return new VictorianChair();
}
public override Table CreateTable()
{
return new VictorianTable();
}
}
// Client
public class Client
{
public static void Main(string[] args)
{
FurnitureFactory modernFactory = new ModernFurnitureFactory();
Chair modernChair = modernFactory.CreateChair();
Table modernTable = modernFactory.CreateTable();
modernChair.SitOn();
modernTable.PlaceOn();
FurnitureFactory victorianFactory = new VictorianFurnitureFactory();
Chair victorianChair = victorianFactory.CreateChair();
Table victorianTable = victorianFactory.CreateTable();
victorianChair.SitOn();
victorianTable.PlaceOn();
}
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a creational pattern that promotes loose coupling and allows for easy switching between different “themes” or variations of objects.
This TypeScript example defines an AbstractFactory interface and concrete factories for ConcreteFactoryA and ConcreteFactoryB. Each factory creates a ProductA and ProductB. The client code interacts with the factories through the AbstractFactory interface, remaining unaware of the specific product types being created. TypeScript’s interfaces and classes naturally lend themselves to this pattern, enforcing type safety and clear structure. The use of abstract classes further clarifies the intended design.
// Abstract Factory Interface
interface AbstractFactory {
createProductA(): ProductA;
createProductB(): ProductB;
}
// Product A Interface
interface ProductA {
operationA(): string;
}
// Product B Interface
interface ProductB {
operationB(): string;
}
// Concrete Product A 1
class ConcreteProductA1 implements ProductA {
operationA(): string {
return "ConcreteProductA1 operation";
}
}
// Concrete Product A 2
class ConcreteProductA2 implements ProductA {
operationA(): string {
return "ConcreteProductA2 operation";
}
}
// Concrete Product B 1
class ConcreteProductB1 implements ProductB {
operationB(): string {
return "ConcreteProductB1 operation";
}
}
// Concrete Product B 2
class ConcreteProductB2 implements ProductB {
operationB(): string {
return "ConcreteProductB2 operation";
}
}
// Concrete Factory 1
class ConcreteFactory1 implements AbstractFactory {
createProductA(): ProductA {
return new ConcreteProductA1();
}
createProductB(): ProductB {
return new ConcreteProductB1();
}
}
// Concrete Factory 2
class ConcreteFactory2 implements AbstractFactory {
createProductA(): ProductA {
return new ConcreteProductA2();
}
createProductB(): ProductB {
return new ConcreteProductB2();
}
}
// Client Code
function clientCode(factory: AbstractFactory) {
const productA = factory.createProductA();
const productB = factory.createProductB();
console.log(productA.operationA());
console.log(productB.operationB());
}
// Usage
const factory1 = new ConcreteFactory1();
clientCode(factory1);
const factory2 = new ConcreteFactory2();
clientCode(factory2);
The Abstract Factory pattern is a creational pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s useful when you need to create different “themes” or configurations of objects.
This JavaScript implementation defines an AbstractFactory interface with methods for creating related objects (e.g., createButton and createInput). Concrete factories (WindowsFactory, MacOSFactory) implement this interface to produce platform-specific object families. A Client then uses the factory to create objects without knowing their concrete types. This approach promotes loose coupling and makes it easy to switch between different object families. The use of classes and interfaces aligns with modern JavaScript’s object-oriented capabilities, and the factory functions encapsulate the object creation logic.
// Abstract Factory Interface
class AbstractFactory {
createButton() {
throw new Error('Method not implemented.');
}
createInput() {
throw new Error('Method not implemented.');
}
}
// Concrete Factory: Windows
class WindowsFactory extends AbstractFactory {
createButton() {
return new WindowsButton();
}
createInput() {
return new WindowsInput();
}
}
// Concrete Factory: macOS
class MacOSFactory extends AbstractFactory {
createButton() {
return new MacOSButton();
}
createInput() {
return new MacOSInput();
}
}
// Product: Button
class Button {
render() {
return "Rendering a Button";
}
}
// Concrete Product: Windows Button
class WindowsButton extends Button {
render() {
return "Rendering a Windows Button";
}
}
// Concrete Product: macOS Button
class MacOSButton extends Button {
render() {
return "Rendering a macOS Button";
}
}
// Product: Input
class Input {
focus() {
return "Input focused";
}
}
// Concrete Product: Windows Input
class WindowsInput extends Input {
focus() {
return "Windows Input focused";
}
}
// Concrete Product: macOS Input
class MacOSInput extends Input {
focus() {
return "macOS Input focused";
}
}
// Client
function clientCode(factory) {
const button = factory.createButton();
const input = factory.createInput();
console.log(button.render());
console.log(input.focus());
}
// Usage
const windowsFactory = new WindowsFactory();
clientCode(windowsFactory);
const macOsFactory = new MacOSFactory();
clientCode(macOsFactory);
The Abstract Factory pattern is a creational pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s useful when you need to create different “flavors” of objects that work together, and you want to decouple the client code from the specific implementations.
This Python example defines abstract classes for Button and Checkbox, and an abstract factory GUIFactory. Concrete factories, WindowsFactory and MacOSFactory, implement the GUIFactory to create platform-specific button and checkbox instances. The client code requests a factory and then uses it to create the necessary GUI elements, remaining unaware of the concrete classes being instantiated. This adheres to Python’s duck typing and promotes loose coupling through interfaces (abstract base classes).
from abc import ABC, abstractmethod
# Abstract Products
class Button(ABC):
@abstractmethod
def render(self):
pass
class Checkbox(ABC):
@abstractmethod
def render(self):
pass
# Abstract Factory
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button:
pass
@abstractmethod
def create_checkbox(self) -> Checkbox:
pass
# Concrete Products (Windows)
class WindowsButton(Button):
def render(self):
return "Rendering a Windows button"
class WindowsCheckbox(Checkbox):
def render(self):
return "Rendering a Windows checkbox"
# Concrete Products (MacOS)
class MacOSButton(Button):
def render(self):
return "Rendering a MacOS button"
class MacOSCheckbox(Checkbox):
def render(self):
return "Rendering a MacOS checkbox"
# Concrete Factories
class WindowsFactory(GUIFactory):
def create_button(self) -> Button:
return WindowsButton()
def create_checkbox(self) -> Checkbox:
return WindowsCheckbox()
class MacOSFactory(GUIFactory):
def create_button(self) -> Button:
return MacOSButton()
def create_checkbox(self) -> Checkbox:
return MacOSCheckbox()
# Client Code
def client_code(factory: GUIFactory):
button = factory.create_button()
checkbox = factory.create_checkbox()
print(button.render())
print(checkbox.render())
# Usage
if __name__ == "__main__":
print("Testing with Windows:")
client_code(WindowsFactory())
print("\nTesting with MacOS:")
client_code(MacOSFactory())
The Abstract Factory pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It’s a “factory of factories,” allowing you to switch between different “looks and feels” or object configurations easily.
The Java code demonstrates this by defining an AbstractFactory interface with a method to create buttons. Concrete factories, WindowsButtonFactory and MacButtonFactory, implement this interface to produce platform-specific buttons. A Client class uses the abstract factory to obtain buttons without knowing their concrete implementation, promoting loose coupling and flexibility. This approach aligns with Java’s OOP principles and interface-based programming, making it easily extensible for new platforms or button types.
// AbstractFactory.java
interface ButtonFactory {
Button createButton();
}
// ConcreteFactory.java
class WindowsButtonFactory implements ButtonFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
}
class MacButtonFactory implements ButtonFactory {
@Override
public Button createButton() {
return new MacButton();
}
}
// Product.java
interface Button {
void click();
}
class WindowsButton implements Button {
@Override
public void click() {
System.out.println("Windows Button Clicked");
}
}
class MacButton implements Button {
@Override
public void click() {
System.out.println("Mac Button Clicked");
}
}
// Client.java
public class Client {
public static void main(String[] args) {
ButtonFactory factory;
// Create Windows buttons
factory = new WindowsButtonFactory();
Button windowsButton = factory.createButton();
windowsButton.click();
// Create Mac buttons
factory = new MacButtonFactory();
Button macButton = factory.createButton();
macButton.click();
}
}