Today I Learned - Rocky Kev

TIL the difference between Factory Pattern and Builder Pattern

POSTED ON:

TAGS:

In OOP, there's a Factory Pattern and a Builder Pattern.

Their goal is to both create objects.

Factory Pattern

// The base class
class Product {
constructor(name, price) {
this.name = name;
this.price = price;
}
}

// Extensions of that class
class Book extends Product {
constructor(name, price, author) {
super(name, price);
this.author = author;
}
}

class Movie extends Product {
constructor(name, price, director) {
super(name, price);
this.director = director;
}
}

// The factory
class ProductFactory {
createProduct(type, name, price, authorOrDirector) {
if (type === 'book') {
return new Book(name, price, authorOrDirector);
} else if (type === 'movie') {
return new Movie(name, price, authorOrDirector);
} else {
throw new Error(`Invalid product type: ${type}`);
}
}
}

And to call it:

const factory = new ProductFactory();

const book = factory.createProduct('book', 'The Great Gatsby', 12.99, 'F. Scott Fitzgerald');
console.log(book); // Book { name: 'The Great Gatsby', price: 12.99, author: 'F. Scott Fitzgerald' }

const movie = factory.createProduct('movie', 'The Godfather', 9.99, 'Francis Ford Coppola');
console.log(movie); // Movie { name: 'The Godfather', price: 9.99, director: 'Francis Ford Coppola' }

Builder Pattern

class Product {
constructor(builder) {
this.name = builder.name;
this.price = builder.price;
this.author = builder.author;
this.director = builder.director;
}
}

class ProductBuilder {
constructor() {
this.name = '';
this.price = 0;
this.author = '';
this.director = '';
}

setName(name) {
this.name = name;
return this;
}

setPrice(price) {
this.price = price;
return this;
}

setAuthor(author) {
this.author = author;
return this;
}

setDirector(director) {
this.director = director;
return this;
}

buildBook() {
return new ProductBuilder()
.setName(this.name)
.setPrice(this.price)
.setAuthor(this.author)
.build();
}

buildMovie() {
return new ProductBuilder()
.setName(this.name)
.setPrice(this.price)
.setDirector(this.director)
.build();
}

build() {
return new Product(this);
}
}

You would then chain each method.

const book = new ProductBuilder()
.setName('The Great Gatsby')
.setPrice(12.99)
.setAuthor('F. Scott Fitzgerald')
.buildBook();

console.log(book); // Product { name: 'The Great Gatsby', price: 12.99, author: 'F. Scott Fitzgerald', director: '' }

const movie = new ProductBuilder()
.setName('The Godfather')
.setPrice(9.99)
.setDirector('Francis Ford Coppola')
.buildMovie();

console.log(movie); // Product { name: 'The Godfather', price: 9.99, author: '', director: 'Francis Ford Coppola' }

The difference

So I still got stuck at understanding when to use one over the other.

My notes:

REFERENCE:
https://stackoverflow.com/a/21494072/4096078
https://stackoverflow.com/a/8959150/4096078
https://en.wikipedia.org/wiki/Factory_method_pattern
https://en.wikipedia.org/wiki/Builder_pattern


Related TILs

Tagged:

TIL Why is TextEncoder a class

My assumed answer - it was for extension. What does reddit commenters have to say about it?

TIL Adapters, proxies, and decorators

An adapter provides a different interface to the object it adapts. A Proxy provides the same interface as its subject. A Decorator adds one or more responsibilities to an object.

TIL super()

When you use super(), it's like you're telling the new object to copy everything from the old object first, and then add or change anything else that's different.