In the "Design Pattern List" Post, you can find a categorized list of design patterns in software engineering. In some upcoming posts, I plan to comprehensively examine these patterns.
Creational Design Patterns
Design Pattern - Factory
1- Simple Factory Pattern
2- Abstract Factory Pattern
3- Factory Method Pattern
1-Simple Factory Pattern
The Simple Factory pattern is like having a special helper, called a "factory", that makes things for you. Imagine you want to create a different type of art piece. Instead of making each piece directly, ask a factory to make the piece for you. This factory knows how to make all types of art pieces.
Here's how it works:
Ask the factory: You tell the factory what kind of art piece you want. For example, you could say: "Hey Factory, make me a blue square."
Factory made: The factory understands the ins and outs of making a blue square art piece, so a piece is made just for you.
Get your art piece: The factory will give you a newly made art piece.
This way you don't have to worry about how each art piece is made. The factory will take care of the details; you just need to put forward your needs.
Key Points:
- Centralized Creation: The production of art pieces is centralized in one location, the factory. Easy Updates: If the method by which pieces are made is altered, only the factory needs to be updated, not every place that makes pieces.
- No specific requirements: You, as the one wanting to know the intricate details, don't have to know how each piece is made. The factory is responsible for that area.
In simpler terms, the Simple Factory Pattern facilitates the creation of different products by having a helper (the factory) take care of the process for you. You simply tell the company what you want, and they will do it for you without having to concern themselves with the complicated aspects.
import React, { useState } from 'react';
// Product: Art Piece
class ArtPiece {
constructor(public color: string, public shape: string) {}
describe(): string {
return `Piece with color ${this.color} and shape ${this.shape}`;
}
}
// Art Piece Types
class BlueSquarePiece extends ArtPiece {
constructor() {
super('blue', 'square');
}
}
class RedCirclePiece extends ArtPiece {
constructor() {
super('red', 'circle');
}
}
// Art Factory
class ArtFactory {
static createArtPiece(type: string): ArtPiece | null {
if (type === 'BlueSquare') {
return new BlueSquarePiece();
} else if (type === 'RedCircle') {
return new RedCirclePiece();
} else {
return null;
}
}
}
// React Component using the Simple Factory pattern
function ArtComponent() {
const [artPiece, setArtPiece] = useState<ArtPiece | null>(null);
const createNewPiece = (type: string) => {
const newPiece = ArtFactory.createArtPiece(type);
setArtPiece(newPiece);
};
return (
<div>
<h1>Art Piece Creation</h1>
{artPiece ? (
<div>
<p>{artPiece.describe()}</p>
</div>
) : (
<p>No art piece created yet</p>
)}
<button onClick={() => createNewPiece('BlueSquare')}>Create Blue Square Piece</button>
<button onClick={() => createNewPiece('RedCircle')}>Create Red Circle Piece</button>
</div>
);
}
export default ArtComponent;
In this updated example, we have an 'ArtFactory', produces different varieties of art components ('BlueSquarePiece' and 'RedCirclePiece'). The 'Art Component' React component employs the factory to create pieces of art based on user input. The simple factory pattern promotes a centralized approach to logic. It facilitates the management and expansion of the creation of various art pieces.
2-Abstract factory pattern
The pattern of the Abstract Factory is similar to having a powerful factory that creates other factories. Each of these factories is responsible for producing related collections of goods. Imagine you're constructing art pieces, and you require different components like edges, corners, and centers. The abstracted factory facilitates the creation of specific factories for each type of art component.
Here's the process:
1- Super Factory: Your facility is large (the abstract factory) and can create other facilities.
2- Specific Factories: Each specific factory that is created by the super factory is dedicated to manufacturing a particular type of art component, such as edges, corners, or centers.
3- Getting Pieces: When you require a particular piece of art, you request that the super facility provide you with a facility for the specific piece of art you want.
4- Factory Produces a Art Piece: The specific factory is responsible for creating the actual art piece for you.
Overall, the Abstract Factory Pattern facilitates the organization of the creation of related objects (like art pieces) by providing a series of factories. This method leaves you with the pieces you need easily, without concern over how each piece is made.
import React, { useState } from 'react';
// Abstract Factory: Art Factory
interface ArtFactory {
createEdgePiece(): ArtPiece;
createCornerPiece(): ArtPiece;
createCenterPiece(): ArtPiece;
}
// Abstract Product: Art Piece
interface ArtPiece {
describe(): string;
}
// Concrete Product: Edge Art Piece
class EdgePiece implements ArtPiece {
describe(): string {
return 'Edge Art Piece';
}
}
// Concrete Product: Corner Art Piece
class CornerPiece implements ArtPiece {
describe(): string {
return 'Corner Art Piece';
}
}
// Concrete Product: Center Art Piece
class CenterPiece implements ArtPiece {
describe(): string {
return 'Center Art Piece';
}
}
// Concrete Factory: Normal Art Factory
class NormalArtFactory implements ArtFactory {
createEdgePiece(): ArtPiece {
return new EdgePiece();
}
createCornerPiece(): ArtPiece {
return new CornerPiece();
}
createCenterPiece(): ArtPiece {
return new CenterPiece();
}
}
// React Component using Abstract Factory pattern
function ArtComponent() {
const [artPieceType, setArtPieceType] = useState<string>(''); // 'Edge', 'Corner', or 'Center'
const [createdPiece, setCreatedPiece] = useState<ArtPiece | null>(null);
const createNewPiece = () => {
if (artPieceType === '') {
alert('Please select an art piece type!');
return;
}
let artFactory: ArtFactory;
// Decide which factory to use based on the selected piece type
if (artPieceType === 'Edge') {
artFactory = new NormalArtFactory();
} else if (artPieceType === 'Corner') {
artFactory = new NormalArtFactory();
} else if (artPieceType === 'Center') {
artFactory = new NormalArtFactory();
} else {
alert('Invalid art piece type!');
return;
}
// Create the specific art piece using the factory
const newPiece = artPieceType === 'Edge'
? artFactory.createEdgePiece()
: artPieceType === 'Corner'
? artFactory.createCornerPiece()
: artFactory.createCenterPiece();
setCreatedPiece(newPiece);
};
return (
<div>
<h1>Art Piece Creation</h1>
<label>Select Art Piece Type: </label>
<select onChange={(e) => setArtPieceType(e.target.value)}>
<option value="">Select</option>
<option value="Edge">Edge</option>
<option value="Corner">Corner</option>
<option value="Center">Center</option>
</select>
<button onClick={createNewPiece}>Create Art Piece</button>
{createdPiece && (
<div>
<p>{createdPiece.describe()}</p>
</div>
)}
</div>
);
}
export default ArtComponent;
In this example:
ArtFactory is the abstract factory interface, and NormalArtFactory is a concrete factory implementing it.
ArtPiece is the abstract product interface, and EdgePiece, CornerPiece, and CenterPiece are concrete products implementing it.
The ArtComponent React component uses the Abstract Factory Pattern to create different types of art pieces based on user selection. The selection determines which concrete factory and product to use.
This example demonstrates how the Abstract Factory Pattern helps organize the creation of related objects (art pieces) by providing a hierarchy of factories, making it easy to add new types of Art pieces in the future.
3- Factory Method Pattern
The Factory Method Pattern is like having a blueprint for creating things, where each thing follows a specific design. Imagine you're making different types of arts, and for each type, you have a unique way of creating pieces. The factory method is like a set of instructions (a method) that tells you how to make a particular type of art piece.
Here's how it works:
1-Blueprint (Interface/Abstract Class): You start with a blueprint that says how a art piece should look or behave. This is like having a set of rules for creating pieces.
2-Factory Method: Then, for each type of art piece, you have a special method (the factory method) that knows how to create that specific piece. It's like having a unique set of instructions for each type of art piece.
3-Creating Pieces: When you want to create a piece, you use the factory method that corresponds to the type of piece you need. This method follows the rules from the blueprint and creates the piece accordingly.
In simpler terms, the Factory Method Pattern provides a way to create different things (like art pieces) by using specific methods (factory methods) that know the details of how each thing should be made. It's like having a set of specialized instructions for creating each type of thing.
Let's consider a simplified example of creating art pieces using the Factory Method Pattern:
import React, { useState } from 'react';
// Product (Art Piece) Interface
interface ArtPiece {
describe(): string;
}
// Concrete Products (Concrete Art Pieces)
class BlueSquarePiece implements ArtPiece {
describe(): string {
return 'Blue Square Art Piece';
}
}
class RedCirclePiece implements ArtPiece {
describe(): string {
return 'Red Circle Art Piece';
}
}
// Creator (Art Factory) Interface
interface ArtFactory {
createArtPiece(): ArtPiece;
}
// Concrete Creators (Concrete Art Factories)
class BlueSquareFactory implements ArtFactory {
createArtPiece(): ArtPiece {
return new BlueSquarePiece();
}
}
class RedCircleFactory implements ArtFactory {
createArtPiece(): ArtPiece {
return new RedCirclePiece();
}
}
// React Component using Factory Method pattern
function ArtComponent() {
const [artPieceType, setArtPieceType] = useState<string>(''); // 'BlueSquare' or 'RedCircle'
const [createdPiece, setCreatedPiece] = useState<ArtPiece | null>(null);
const createNewPiece = () => {
if (artPieceType === '') {
alert('Please select a art piece type!');
return;
}
let artFactory: ArtFactory;
// Decide which factory to use based on the selected piece type
if (artPieceType === 'BlueSquare') {
artFactory = new BlueSquareFactory();
} else if (artPieceType === 'RedCircle') {
artFactory = new RedCircleFactory();
} else {
alert('Invalid art piece type!');
return;
}
// Use the factory method to create the specific art piece
const newPiece = artFactory.createArtPiece();
setCreatedPiece(newPiece);
};
return (
<div>
<h1>Art Piece Creation</h1>
<label>Select Art Piece Type: </label>
<select onChange={(e) => setArtPieceType(e.target.value)}>
<option value="">Select</option>
<option value="BlueSquare">Blue Square</option>
<option value="RedCircle">Red Circle</option>
</select>
<button onClick={createNewPiece}>Create Art Piece</button>
{createdPiece && (
<div>
<p>{createdPiece.describe()}</p>
</div>
)}
</div>
);
}
export default ArtComponent;
In this example:
-ArtPiece is the product interface representing the art
pieces.
-BlueSquarePiece and RedCirclePiece are concrete products
implementing the ArtPiece interface.
-ArtFactory is the creator interface declaring the factory
method createArtPiece.
-BlueSquareFactory and RedCircleFactory are concrete creators
implementing the ArtFactory interface and providing the
specific factory methods.
The React component ArtComponent uses the Factory Method Pattern to create puzzle pieces based on the user's selection, demonstrating how specific factories create different types of puzzle pieces.
Summary:
Simple Factory Pattern: Provides a centralized factory class to create different types of objects; suitable for straightforward scenarios.
Abstract Factory Pattern: Involves multiple factories organized into families; focuses on creating related or dependent objects.
Factory Method Pattern: Uses an abstract creator class with a factory method; delegates object creation to subclasses, promoting flexibility and extensibility.
Choosing between these patterns depends on the specific requirements of the system and the desired level of flexibility in object creation. Simple Factory is the most basic, while Abstract Factory and Factory Methods offer more sophisticated approaches for creating families of objects and allowing for more dynamic instantiation processes.
Top comments (2)
Appreciate the sentiment here having to try and clean up an e-commerce front end theme that the Dev has utilised your exact example of adding and removing classes with js. It's horrible checking through various states to see what classes are being added removed at any point in time, couple this with different breakpoints and media queries being used it's a nightmare.
I learnt a few rough lessons in js around mutation of variables and the mess you can get into. I feel as though messing with classes can actually lead you down the same path. I like the data attribute idea, you can clearly see what is being targeted and it's before / after state options.
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍
Some comments have been hidden by the post's author - find out more