.
================================================
FILE: README.md
================================================
Join Free Newsletter
This repository contains resources to learn Low Level Design (LLD) / Object Oriented Design (OOD) and prepare for interviews. It covers OOP fundamentals, design patterns, UML, concurrency and commonly asked interview questions.
👉 For a better and more comprehensive experience, checkout the [LLD page at AlgoMaster.io](https://algomaster.io/learn/lld)
## 🧱 OOP Fundamentals
- [Classes and Objects](https://algomaster.io/learn/lld/classes-and-objects)
- [Enums](https://algomaster.io/learn/lld/enums)
- [Interfaces](https://algomaster.io/learn/lld/interfaces)
- [Encapsulation](https://algomaster.io/learn/lld/encapsulation)
- [Abstraction](https://algomaster.io/learn/lld/abstraction)
- [Inheritance](https://algomaster.io/learn/lld/inheritance)
- [Polymorphism](https://algomaster.io/learn/lld/polymorphism)
## 🔗 Class Relationships
- [Association](https://algomaster.io/learn/lld/association)
- [Aggregation](https://algomaster.io/learn/lld/aggregation)
- [Composition](https://algomaster.io/learn/lld/composition)
- [Dependency](https://algomaster.io/learn/lld/dependency)
## 🧭 Design Principles
- [DRY Principle](https://algomaster.io/learn/lld/dry)
- [YAGNI Principle](https://algomaster.io/learn/lld/yagni)
- [KISS Principle](https://algomaster.io/learn/lld/kiss)
- [SOLID Principles with Pictures](https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898)
- [SOLID Principles with Code](https://blog.algomaster.io/p/solid-principles-explained-with-code)
## 🧩 Design Patterns
| **Creational Patterns** | **Structural Patterns** | **Behavioral Patterns** |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| [Singleton](https://algomaster.io/learn/lld/singleton) | [Adapter](https://algomaster.io/learn/lld/adapter) | [Iterator](https://algomaster.io/learn/lld/iterator) |
| [Factory Method](https://algomaster.io/learn/lld/factory-method) | [Bridge](https://algomaster.io/learn/lld/bridge) | [Observer](https://algomaster.io/learn/lld/observer) |
| [Abstract Factory](https://algomaster.io/learn/lld/abstract-factory) | [Composite](https://algomaster.io/learn/lld/composite) | [Strategy](https://algomaster.io/learn/lld/strategy) |
| [Builder](https://algomaster.io/learn/lld/builder) | [Decorator](https://algomaster.io/learn/lld/decorator) | [Command](https://algomaster.io/learn/lld/command) |
| [Prototype](https://algomaster.io/learn/lld/prototype) | [Facade](https://algomaster.io/learn/lld/facade) | [State](https://algomaster.io/learn/lld/state) |
| | [Flyweight](https://algomaster.io/learn/lld/flyweight) | [Template Method](https://algomaster.io/learn/lld/template-method) |
| | [Proxy](https://algomaster.io/learn/lld/proxy) | [Visitor](https://algomaster.io/learn/lld/visitor) |
| | | [Mediator](https://algomaster.io/learn/lld/mediator) |
| | | [Memento](https://algomaster.io/learn/lld/memento) |
| | | [Chain of Responsibility](https://algomaster.io/learn/lld/chain-of-responsibility) |
## 🗂️ UML
- [Class Diagram](https://algomaster.io/learn/lld/class-diagram)
- [Use Case Diagram](https://algomaster.io/learn/lld/use-case-diagram)
- [Sequence Diagram](https://algomaster.io/learn/lld/sequence-diagram)
- [Activity Diagram](https://algomaster.io/learn/lld/activity-diagram)
- [State Machine Diagram](https://algomaster.io/learn/lld/state-machine-diagram)
## ⏱️ Concurrency and Multi-threading Concepts
### Concurrency 101
- [Introduction to Concurrency](https://algomaster.io/learn/concurrency-interview/introduction-to-concurrency)
- [Concurrency vs Parallelism](https://algomaster.io/learn/concurrency-interview/concurrency-vs-parallelism)
- [Processes vs Threads](https://algomaster.io/learn/concurrency-interview/processes-vs-threads)
- [Thread Lifecycle and States](https://algomaster.io/learn/concurrency-interview/thread-lifecycle-and-states)
- [Race Conditions and Critical Sections](https://algomaster.io/learn/concurrency-interview/race-conditions-and-critical-sections)
### Synchronization Primitives
- [Mutex (Mutual Exclusion)](https://algomaster.io/learn/concurrency-interview/mutex)
- [Semaphores](https://algomaster.io/learn/concurrency-interview/semaphores)
- [Condition Variables](https://algomaster.io/learn/concurrency-interview/condition-variables)
- [Coarse-grained vs Fine-grained Locking](https://algomaster.io/learn/concurrency-interview/coarse-vs-fine-grained-locking)
- [Reentrant Locks](https://algomaster.io/learn/concurrency-interview/reentrant-locks)
- [Try-Lock and Timed Locking](https://algomaster.io/learn/concurrency-interview/try-lock-and-timed-locking)
- [Compare-and-Swap (CAS)](https://algomaster.io/learn/concurrency-interview/compare-and-swap)
### Concurrency Challenges
- [Deadlock](https://algomaster.io/learn/concurrency-interview/deadlock)
- [Livelock](https://algomaster.io/learn/concurrency-interview/livelock)
### Concurrency Patterns
- [Signaling Pattern](https://algomaster.io/learn/concurrency-interview/signaling-pattern)
- [Thread Pool Pattern](https://algomaster.io/learn/concurrency-interview/thread-pool-pattern)
- [Producer-Consumer Pattern](https://algomaster.io/learn/concurrency-interview/producer-consumer-pattern)
- [Reader-Writer Pattern](https://algomaster.io/learn/concurrency-interview/reader-writer-pattern)
## ✅ [How to Answer a LLD Interview Problem](https://blog.algomaster.io/p/how-to-answer-a-lld-interview-problem)
## 💻 Low Level Design Interview Problems
### Easy Problems
- [Design Parking Lot](problems/parking-lot.md)
- [Design Stack Overflow](problems/stack-overflow.md)
- [Design a Vending Machine](problems/vending-machine.md)
- [Design Logging Framework](problems/logging-framework.md)
- [Design Traffic Signal Control System](problems/traffic-signal.md)
- [Design Coffee Vending Machine](problems/coffee-vending-machine.md)
- [Design a Task Management System](problems/task-management-system.md)
### Medium Problems
- [Design ATM](problems/atm.md)
- [Design LinkedIn](problems/linkedin.md)
- [Design LRU Cache](problems/lru-cache.md)
- [Design Tic Tac Toe Game](problems/tic-tac-toe.md)
- [Design Pub Sub System](problems/pub-sub-system.md)
- [Design an Elevator System](problems/elevator-system.md)
- [Design Car Rental System](problems/car-rental-system.md)
- [Design an Online Auction System](problems/online-auction-system.md)
- [Design Hotel Management System](problems/hotel-management-system.md)
- [Design a Digital Wallet Service](problems/digital-wallet-service.md)
- [Design Airline Management System](problems/airline-management-system.md)
- [Design a Library Management System](problems/library-management-system.md)
- [Design a Social Network like Facebook](problems/social-networking-service.md)
- [Design Restaurant Management System](problems/restaurant-management-system.md)
- [Design a Concert Ticket Booking System](problems/concert-ticket-booking-system.md)
### Hard Problems
- [Design CricInfo](problems/cricinfo.md)
- [Design Splitwise](problems/splitwise.md)
- [Design Chess Game](problems/chess-game.md)
- [Design a Snake and Ladder game](problems/snake-and-ladder.md)
- [Design Ride-Sharing Service like Uber](problems/ride-sharing-service.md)
- [Design Course Registration System](problems/course-registration-system.md)
- [Design Movie Ticket Booking System](problems/movie-ticket-booking-system.md)
- [Design Online Shopping System like Amazon](problems/online-shopping-service.md)
- [Design Online Stock Brokerage System](problems/online-stock-brokerage-system.md)
- [Design Music Streaming Service like Spotify](problems/music-streaming-service.md)
- [Design Online Food Delivery Service like Swiggy](problems/food-delivery-service.md)
## ⏱️ Concurrency and Multi-threading Problems
- [Print FooBar Alternately](https://algomaster.io/learn/concurrency-interview/print-foobar-alternately)
- [Print Zero Even Odd](https://algomaster.io/learn/concurrency-interview/print-zero-even-odd)
- [Fizz Buzz Multithreaded](https://algomaster.io/learn/concurrency-interview/fizz-buzz-multithreaded)
- [Building H2O Molecule](https://algomaster.io/learn/concurrency-interview/building-h2o)
- [Design Thread-Safe Cache with TTL](https://algomaster.io/learn/concurrency-interview/design-thread-safe-cache-with-ttl)
- [Design Concurrent HashMap](https://algomaster.io/learn/concurrency-interview/design-concurrent-hashmap)
- [Design Thread-Safe Blocking Queue](https://algomaster.io/learn/concurrency-interview/design-thread-safe-blocking-queue)
- [Design Concurrent Bloom Filter](https://algomaster.io/learn/concurrency-interview/design-concurrent-bloom-filter)
- [Multi-threaded Merge Sort](https://algomaster.io/learn/concurrency-interview/multi-threaded-merge-sort)
## 📇 Courses
- [Master LLD Interviews - AlgoMaster.io](https://algomaster.io/learn/lld/course-introduction)
- [Master Concurrency Interviews - AlgoMaster.io](https://algomaster.io/learn/concurrency-interview)
## 📚 Books
- [Head First Design Patterns](https://www.amazon.in/dp/9385889753)
- [Clean Code](https://www.amazon.in/dp/B001GSTOAM)
- [Refactoring: Improving the Design of Existing Code](https://www.amazon.in/dp/0134757599)
## 📩 Newsletter
- [AlgoMaster Newsletter](https://blog.algomaster.io/)
## Additional resources
- [Coursera - Object-Oriented Design](https://www.coursera.org/learn/object-oriented-design)
- [Coursera - Design Patterns](https://www.coursera.org/learn/design-patterns)
- [Github - Awesome Design Patterns](https://github.com/DovAmir/awesome-design-patterns)
## 🤝 Contributing
Contributions are welcome! If you'd like to add a new problem, improve existing content, or fix errors:
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature-name`
3. Commit your changes: `git commit -m 'Add some feature'`
4. Push to the branch: `git push origin feature/your-feature-name`
5. Submit a pull request
Please make sure to update Readme files and documentation as appropriate.
---
If you find this resource helpful, please give it a star and share it with others!
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Chain of Responsibilites/main.js
================================================
const {
InternetConnectionTeam,
InternetSupportTeam,
PhoneConnectionTeam,
PhoneSupportTeam,
} = require("./supportRequest");
const phoneSupport = new PhoneSupportTeam(null);
const phoneConnection = new PhoneConnectionTeam(phoneSupport);
const internetSupport = new InternetSupportTeam(phoneConnection);
const internetConnection = new InternetConnectionTeam(internetSupport);
console.log("Problem 1 - internet connection");
internetConnection.handleRequest("internet", "newConnection");
console.log("Problem 2 - phone connection");
internetConnection.handleRequest("phone", "problem");
console.log("Problem 3 - phone support");
internetConnection.handleRequest("phone", "problem");
console.log("Problem 4 - Invalid support");
internetConnection.handleRequest("Laptop", "problem");
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Chain of Responsibilites/supportRequest.js
================================================
// Creating a chain for attaining support team
class supportHandler {
constructor(nextHandler) {
this.nextHandler = nextHandler;
}
// Method to handle the request
handleRequest(request, type) {
if (this.nextHandler) {
console.log("Passing to the next executive team to resolve your issue");
this.nextHandler.handleRequest(request, type);
} else {
console.log("No further handlers available to process the request.");
}
}
}
// First level internet support team for connection
class InternetConnectionTeam extends supportHandler {
handleRequest(request, type) {
if (request === "internet" && type === "newConnection") {
console.log("Your newConnection request is taken. Thank you! 🙂");
} else if (request === "internet" && type === "problem") {
console.log(
"Seems you have an issue; we will redirect to the support team"
);
super.handleRequest(request, type); // Transferring to the next team
} else {
console.log(
"Unknown request type in InternetConnectionTeam. Passing to next team."
);
super.handleRequest(request, type); // Transfer to the next team
}
}
}
// Second level internet support team for problem
class InternetSupportTeam extends supportHandler {
handleRequest(request, type) {
if (request === "internet" && type === "problem") {
console.log("Your internet request is taken. Thank you! 🙂");
} else {
console.log(
"Unknown request type in InternetSupportTeam. Passing to next team."
);
super.handleRequest(request, type); // Transferring to the next team
}
}
}
// Third level connection
class PhoneConnectionTeam extends supportHandler {
handleRequest(request, type) {
if (request === "phone" && type === "newConnection") {
console.log("Your newConnection request is taken. Thank you! 🙂");
} else if (request === "phone" && type === "problem") {
console.log(
"Seems you have an issue; we will redirect to the support team"
);
super.handleRequest(request, type); // Transferring to the next team
} else {
console.log(
"Unknown request type in PhoneConnectionTeam. Passing to next team."
);
super.handleRequest(request, type); // Transferring to the next team
}
}
}
// Last level phone support team for problem
class PhoneSupportTeam extends supportHandler {
handleRequest(request, type) {
if (request === "phone" && type === "problem") {
console.log("Your phone request is taken. Thank you! 🙂");
} else {
console.log(
"Unknown request type in PhoneSupportTeam. This is the last support level."
);
}
}
}
// Main module export
module.exports = {
InternetConnectionTeam,
InternetSupportTeam,
PhoneConnectionTeam,
PhoneSupportTeam,
};
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Command Design Pattern/command.js
================================================
// Abstract Command
class Command {
execute() {}
}
// Concrete Command
class LightOnCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.turnOn();
}
}
class LightOffCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.turnOff();
}
}
// Concrete Command to turn on the fan
class FanOnCommand extends Command {
constructor(fan) {
super();
this.fan = fan;
}
execute() {
this.fan.turnOn();
}
}
// Concrete Command to turn off the fan
class FanOffCommand extends Command {
constructor(fan) {
super();
this.fan = fan;
}
execute() {
this.fan.turnOff();
}
}
module.exports = {
LightOnCommand,
LightOffCommand,
FanOnCommand,
FanOffCommand,
};
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Command Design Pattern/invoker.js
================================================
// Invoker class
class RemoteControl {
setCommand(command) {
this.command = command;
}
pressButton() {
this.command.execute();
}
}
module.exports = {RemoteControl}
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Command Design Pattern/main.js
================================================
// Client code
const {
LightOnCommand,
LightOffCommand,
FanOnCommand,
FanOffCommand,
} = require("./command");
const{Light, Fan} = require('./receiver')
const {RemoteControl} = require ('./invoker')
const light = new Light();
const fan = new Fan();
const lightOn = new LightOnCommand(light);
const lightOff = new LightOffCommand(light);
const fanOn = new FanOnCommand(fan);
const fanOff = new FanOffCommand(fan);
const remote = new RemoteControl();
// Turning on the light
remote.setCommand(lightOn);
remote.pressButton(); // Output: "The light is on."
// Turning off the light
remote.setCommand(lightOff);
remote.pressButton(); // Output: "The light is off."
// Turning on the fan
remote.setCommand(fanOn);
remote.pressButton(); // Output: "The fan is on."
// Turning off the fan
remote.setCommand(fanOff);
remote.pressButton(); // Output: "The fan is off."
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Command Design Pattern/receiver.js
================================================
// Receiver for Light
class Light {
turnOn() {
console.log("The light is on.");
}
turnOff() {
console.log("The light is off.");
}
}
// Receiver for Fan
class Fan {
turnOn() {
console.log("The fan is on.");
}
turnOff() {
console.log("The fan is off.");
}
}
module.exports = { Light, Fan };
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Iterator Design Pattern/aggregate.js
================================================
const { LibraryIterator } = require("./iterator");
const Book = require("./book");
class Aggregate {
createIterator() {
throw new Error("Method 'createIterator()' must be implemented.");
}
}
class ConcreteAggregate extends Aggregate {
constructor() {
super();
this.books = [];
}
addBook(book) {
this.books.push(book);
}
createIterator() {
return new LibraryIterator(this.books);
}
}
module.exports = ConcreteAggregate;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Iterator Design Pattern/book.js
================================================
class Book {
constructor(title, author) {
this.title = title;
this.author = author;
}
getDetails() {
return `${this.title} by ${this.author}`;
}
}
module.exports = Book;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Iterator Design Pattern/iterator.js
================================================
class Iterator {
next() {
throw new Error("Method 'next()' must be implemented.");
}
hasNext() {
throw new Error("Method 'hasNext()' must be implemented.");
}
}
// Concrete Iterator
class LibraryIterator extends Iterator {
constructor(collection) {
super();
this.collection = collection;
this.index = 0;
}
hasNext() {
return this.index < this.collection.length;
}
next() {
console.log("Current index: " + this.index);
return this.collection[this.index++];
}
}
module.exports = { Iterator, LibraryIterator };
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Iterator Design Pattern/main.js
================================================
const ConcreteAggregate = require("./aggregate");
const Book = require("./book");
const library = new ConcreteAggregate();
// Adding books to the library
library.addBook(new Book("To Kill a Mockingbird", "Harper Lee"));
library.addBook(new Book("1984", "George Orwell"));
library.addBook(new Book("The Great Gatsby", "F. Scott Fitzgerald"));
library.addBook(new Book("Moby Dick", "Herman Melville"));
// Creating an iterator for the library
const iterator = library.createIterator();
// Iterating through the collection of books
while (iterator.hasNext()) {
const book = iterator.next();
console.log(book.getDetails());
}
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Mediator Design Pattern/main.js
================================================
// Client code to handle users registration and messages communication
const User = require("./user");
const ChatRoom = require("./mediator");
// Object for chatRoom (mediator)
const chatRoom = new ChatRoom();
// Objects for users
const user1 = new User("User1", chatRoom);
const user2 = new User("User2", chatRoom);
const user3 = new User("User3", chatRoom);
// Register users with chatRoom
chatRoom.register(user1);
chatRoom.register(user2);
chatRoom.register(user3);
// Send message
user1.send("Hello everyone!");
user2.send("Hi User1!");
user3.send("Hi User2!");
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Mediator Design Pattern/mediator.js
================================================
// Abstract Mediator
class Mediator {
register(user) {
throw new Error("Method 'register()' must be implemented");
}
send(message, user) {
throw new Error("Method 'send()' must be implemented");
}
}
// Concrete Mediator
class ChatRoom extends Mediator {
constructor() {
super();
this.users = [];
}
register(user) {
this.users.push(user);
}
send(message, from) {
this.users.forEach((user) => {
if (user !== from) {
// send senderMessage only to other users
user.receive(message, from);
}
});
}
}
module.exports = ChatRoom;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Mediator Design Pattern/user.js
================================================
class User {
constructor(name, mediator) {
this.name = name;
this.mediator = mediator;
}
send(message) {
console.log(`${this.name} sent: ${message}`);
this.mediator.send(message, this);
}
receive(message) {
console.log(`${this.name} receives message: ${message}`);
}
}
module.exports = User;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/Example2/canvas.js
================================================
// Import CanvasMemento from memento.js
const CanvasMemento = require("./memento"); // <-- Add this line
class DrawingCanvas {
constructor() {
this.shapes = []; // The current shapes drawn on the canvas
}
// Method to draw a new shape
addShape(shape) {
this.shapes.push(shape);
}
// Method to remove the last added shape (simulating undo)
removeLastShape() {
this.shapes.pop();
}
// Create a memento (save the current state)
save() {
return new CanvasMemento([...this.shapes]); // Copy the current shapes to a new Memento
}
// Restore the canvas state from a memento
restore(memento) {
this.shapes = memento.getState(); // Replace current shapes with the saved shapes
}
// Print all shapes (to simulate displaying them on the canvas)
show() {
console.log("Current shapes on canvas:", this.shapes);
}
}
module.exports = DrawingCanvas;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/Example2/careTaker.js
================================================
// CareTaker -> Manages mementos
class History {
constructor() {
this.mementos = []; // List of saved mementos
}
// Save a memento
saveMemento(memento) {
this.mementos.push(memento);
}
// Get a memento
getMemento(index) {
return this.mementos[index];
}
// Remove the last memento
removeMemento() {
return this.mementos.pop();
}
getLatestMemento() {
return this.mementos.length > 0
? this.mementos[this.mementos.length - 1]
: null;
}
removeLastMemento() {
if (this.mementos.length > 0) {
this.mementos.pop();
}
}
}
module.exports = History;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/Example2/main.js
================================================
const DrawingCanvas = require('./canvas');
const CanvasMemento = require('./memento');
const History = require('./careTaker');
// Create a new drawing canvas (Originator)
const canvas = new DrawingCanvas();
// Create a new History (Caretaker)
const history = new History();
// Draw some shapes on the canvas
canvas.addShape("Circle");
canvas.addShape("Square");
// Show current state of canvas
console.log("Initial Drawing:");
canvas.show(); // Output: Circle, Square
// Save the current state of the canvas
history.saveMemento(canvas.save()); // Save: Circle, Square
// Draw more shapes
canvas.addShape("Triangle");
canvas.addShape("Hexagon");
// Show current state of canvas
console.log("\nAfter Drawing More Shapes:");
canvas.show(); // Output: Circle, Square, Triangle, Hexagon
// Save the current state again
history.saveMemento(canvas.save()); // Save: Circle, Square, Triangle, Hexagon
// Draw another shape
canvas.addShape("Pentagon");
// Show current state of canvas
console.log("\nAfter Adding Pentagon:");
canvas.show(); // Output: Circle, Square, Triangle, Hexagon, Pentagon
// Undo the last action by restoring the previous memento
canvas.restore(history.getLatestMemento());
history.removeLastMemento(); // Remove the latest snapshot
console.log("\nAfter Undo (Restoring Previous State):");
canvas.show(); // Output: Circle, Square, Triangle, Hexagon
// Undo another action
canvas.restore(history.getLatestMemento());
history.removeLastMemento(); // Remove the latest snapshot
console.log("\nAfter Another Undo:");
canvas.show(); // Output: Circle, Square
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/Example2/memento.js
================================================
// Memento -> Stores the snapshot of canvas state
class CanvasMemento {
constructor(state) {
this.state = state; // The saved shapes at this point
}
// Returns the saved state
getState() {
return this.state;
}
}
module.exports = CanvasMemento;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/careTaker.js
================================================
// careTaker.js
class CareTaker {
constructor() {
this.mementos = [];
}
saveMemento(memento) {
this.mementos.push(memento);
}
getMemento(index) {
return this.mementos[index];
}
}
module.exports = CareTaker;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/main.js
================================================
const TextEditor = require("./orginator");
const Caretaker = require("./careTaker");
// Create a TextEditor instance
const textEditor = new TextEditor();
const caretaker = new Caretaker();
// Write some content
textEditor.write("Hello, ");
caretaker.saveMemento(textEditor.save()); // Save the current state
textEditor.write("world!");
console.log(textEditor.getContent()); // Output: "Hello, world!"
caretaker.saveMemento(textEditor.save()); // Save the current state again
textEditor.write(" How are you?");
console.log(textEditor.getContent()); // Output: "Hello, world! How are you?"
// Restore to the previous state
textEditor.restore(caretaker.getMemento(1));
console.log(textEditor.getContent()); // Output: "Hello, world!"
// Restore to the initial state
textEditor.restore(caretaker.getMemento(0));
console.log(textEditor.getContent()); // Output: "Hello, "
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/memento.js
================================================
// Memento
class Memento {
constructor(state) {
this.state = state;
}
getState() {
return this.state;
}
}
module.exports = Memento;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Memento Design Pattern/orginator.js
================================================
// Orginator file
const Memento = require("./memento");
class TextEditor {
constructor() {
this.content = "";
}
write(content) {
this.content += content;
}
getContent() {
return this.content;
}
save() {
return new Memento(this.content);
}
restore(memento) {
this.content = memento.getState();
}
}
module.exports = TextEditor;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Observer Design Pattern/main.js
================================================
const { WebUI, MobileUI } = require("./observer");
const WeatherStation = require("./publisher");
// Create a WeatherStation instance
const weatherStation = new WeatherStation();
// Create observers
const webUI = new WebUI();
const mobileUI = new MobileUI();
// Register observers with the weather station
weatherStation.addObserver(webUI);
weatherStation.addObserver(mobileUI);
// Change the temperature
weatherStation.setTemperature(25); // Notify the data all observers
weatherStation.setTemperature(30); // Notify the updated data all observers
// Adding another observer
const webUI2 = new WebUI();
weatherStation.addObserver(webUI2);
weatherStation.setTemperature(35);
// Removing an observer
weatherStation.removeObserver(webUI);
weatherStation.setTemperature(40);
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Observer Design Pattern/observer.js
================================================
class Observer {
update(temperature) {
throw new Error("Method 'update()' must be implemented");
}
}
class WebUI extends Observer {
update(temperature) {
console.log(`Temperature showing in web UI: ${temperature}`);
}
}
class MobileUI extends Observer {
update(temperature) {
console.log(`Temperature showing in mobile UI: ${temperature}`);
}
}
module.exports = {
WebUI,
MobileUI,
};
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Observer Design Pattern/publisher.js
================================================
class WeatherStation {
constructor() {
this.observers = [];
this.temperature = 0;
}
//Method to add Subscribers to the list
addObserver(observer) {
this.observers.push(observer);
}
// Remove Subscribers from the list
removeObserver(observer) {
this.observers = this.observers.filter((obs) => obs !== observer);
}
// Notify all subscribers
notifyObservers() {
this.observers.forEach((observer) => observer.update(this.temperature));
}
//Method to set the temperature
setTemperature(temperature) {
this.temperature = temperature;
this.notifyObservers();
}
}
module.exports = WeatherStation;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/State Design Pattern/context.js
================================================
const {Idle} = require("./state");
// Context Class
class Phone {
constructor() {
this.state = new Idle(); // Inital state
}
setState(state) {
this.state = state;
}
alert() {
this.state.alert();
}
answer() {
this.state.answer(this);
}
hangup() {
this.state.hangup(this);
}
}
module.exports = Phone;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/State Design Pattern/main.js
================================================
const Phone = require("./context");
const {Ringing} = require("./state");
const phone = new Phone();
phone.alert(); // Output: Phone is idle.
phone.answer(); // Output: No incoming call to answer.
phone.setState(new Ringing());
phone.alert(); // Output: Phone is ringing...
phone.answer(); // Output: Answering the call.
phone.alert(); // Output: Phone is in a call.
phone.hangup(); // Output: Hanging up the call.
phone.alert(); // Output: Phone is idle.
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/State Design Pattern/state.js
================================================
// Abstract class for phoneState
class PhoneState {
alert() {}
answer() {}
hangup() {}
}
// Concerte Class for phoneState
// State-1 : Phone is in Ringing State
class Ringing extends PhoneState {
alert() {
console.log("Phone is ringing...");
}
answer(context) {
console.log("Phone is answering...");
context.setState(new InCall());
}
hangup() {
console.log("Cannot hangup while ringing");
}
}
// State-2 : Phone is in InCall State
class InCall extends PhoneState {
alert() {
console.log("Phone is in call...");
}
answer() {
console.log("Cannot answer while in call");
}
hangup(context) {
console.log("Phone is hanging up...");
context.setState(new Idle());
}
}
// State-3 : Phone is in Idle State
class Idle extends PhoneState {
alert() {
console.log("Phone is idle...");
}
answer() {
console.log("Phone is answering...");
this.hangup();
}
hangup() {
console.log("Cannot hangup while idle");
}
}
module.exports = { Ringing, InCall, Idle };
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Strategy Design Pattern/main.js
================================================
const ShoppinCart = require("./shoppingCart_Context");
const { Cash, UPI, Card, InternetBanking } = require("./paymentStrategy");
// Creating a shopping cart Instance
const shoppingCart = new ShoppinCart();
// Adding items to the shopping cart
shoppingCart.addItem({ name: "Laptop", price: 500 });
shoppingCart.addItem({ name: "Mobile", price: 200 });
shoppingCart.addItem({ name: "TV", price: 1000 });
// View cart after adding items
shoppingCart.viewCart();
// Checkout in method - 1
shoppingCart.setPaymentMethod(new Card(123456789, 123));
shoppingCart.checkout();
// Checkout in method - 2
shoppingCart.setPaymentMethod(new Cash(123));
shoppingCart.checkout();
// Checkout in method - 3
shoppingCart.setPaymentMethod(new UPI(123456789, 123));
shoppingCart.checkout();
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Strategy Design Pattern/paymentStrategy.js
================================================
// Strategy class
// Abstract class
class PaymentGateway {
pay(amount) {
throw new Error("Method 'pay()' must be implemented!");
}
}
// Concrete class for paymentGateway
// Cash payment method
class Cash extends PaymentGateway {
pay(amount) {
console.log(`Payment of ${amount} done using Cash`);
}
}
// UPI payment method
class UPI extends PaymentGateway {
constructor(UPI_ID, UPI_PIN) {
super();
this.UPI_ID = UPI_ID;
this.UPI_PIN = UPI_PIN;
}
pay(amount) {
console.log(
`Payment of ${amount} done using UPI with ID ${this.UPI_ID} and PIN ${this.UPI_PIN}`
);
}
}
// Card payment method
class Card extends PaymentGateway {
constructor(cardNumber, CVV) {
super();
this.cardNumber = cardNumber;
this.CVV = CVV;
}
pay(amount) {
console.log(
`Payment of ${amount} done using Card Number ${this.cardNumber} and CVV ${this.CVV}`
);
}
}
// Internet Banking payment method
class InternetBanking extends PaymentGateway {
constructor(accountNumber, IFSC) {
super();
this.accountNumber = accountNumber;
this.IFSC = IFSC;
}
pay(amount) {
console.log(
`Payment of ${amount} done using Internet Banking with Account Number ${this.accountNumber} and IFSC ${this.IFSC}`
);
}
}
module.exports = { Cash, UPI, Card, InternetBanking };
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Strategy Design Pattern/shoppingCart_Context.js
================================================
// Context file as shoppingCart class
class ShoppinCart {
constructor() {
this.items = [];
this.paymentMethod = null;
}
// Adding items to the shopping cart
addItem(item) {
this.items.push(item);
}
// View cart after adding items
viewCart() {
console.log("Your cart contains: ");
this.items.forEach((item, index) => {
console.log(`${index + 1}. ${item.name} - $${item.price}`);
});
}
// Selecting the payment method
setPaymentMethod(paymentMethod) {
this.paymentMethod = paymentMethod;
}
// Checkout
checkout() {
// Adding reduce method to calculate the total bill
const Total = this.items.reduce((total, item) => total + item.price, 0);
// Checks if paymentMethod is choosen to proceed for checkout
if (this.paymentMethod) {
console.log(`Total Bill: $${Total}`);
this.paymentMethod.pay(Total);
} else {
console.log("Please confirm your payment method");
}
}
}
module.exports = ShoppinCart;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Template Design Pattern/beverages.js
================================================
// Abstract class in Template Pattern
class Food {
prepareFood() {
this.boilWater();
this.brew();
this.pourInCup();
this.addCondiments();
this.noNeedVegetables(); // Setting as optional from template pattern
}
boilWater() {
console.log("Boiling the water...");
}
brew() {
throw new error("Method 'brew()' must be implemented");
}
pourInCup() {
console.log("Pouring into cup...");
}
addCondiments() {
throw new error("Method 'addCondiments()' must be implemented");
}
// private method
noNeedVegetables() {
if (this.shouldAddVegetables()) {
this.addVegetables();
}
}
addVegetables() {
console.log("No vegetables added here!");
}
// Default is set to false
shouldAddVegetables() {
return false;
}
}
module.exports = Food;
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Template Design Pattern/beveragesTypes.js
================================================
// Concrete classes for Food
// Make using of superClasses from templatePattern and modifying here (subClasses)
const Food = require("./beverages");
class Tea extends Food {
brew() {
console.log("Steeping the tea...");
}
addCondiments() {
console.log("Adding lemon...");
}
addVegetables() {
console.log("Adding mint leaves to tea...");
}
shouldAddVegetables() {
return true; // Tea includes vegetables
}
}
class Coffee extends Food {
brew() {
console.log("Dripping coffee through filter...");
}
addCondiments() {
console.log("Adding sugar and milk...");
}
}
module.exports = { Tea, Coffee };
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Template Design Pattern/main.js
================================================
const { Tea, Coffee } = require("./beveragesTypes");
// Meal 1
console.log("Preparing Tea..");
const tea = new Tea();
tea.prepareFood();
console.log(""); // For spacing
// Meal 2
console.log("Preparing Coffee..");
const coffee = new Coffee();
coffee.prepareFood();
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Visitor Design Pattern/element.js
================================================
// element.js
class Shape {
accept(visitor) {
throw new Error("This method should be overridden!");
}
}
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
accept(visitor) {
visitor.visitCircle(this);
}
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
accept(visitor) {
visitor.visitRectangle(this);
}
}
module.exports = {Circle,Rectangle};
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Visitor Design Pattern/main.js
================================================
const { Circle, Rectangle } = require("./element");
const { AreaVisitor, PerimeterVisitor } = require("./visitor");
const shapes = [
new Circle(5),
new Rectangle(10, 20),
];
// Create visitors
const areaVisitor = new AreaVisitor();
const perimeterVisitor = new PerimeterVisitor();
// Calculate areas
console.log("Calculating Areas:");
shapes.forEach((shape) => {
shape.accept(areaVisitor);
});
// Calculate perimeters
console.log("\nCalculating Perimeters:");
shapes.forEach((shape) => {
shape.accept(perimeterVisitor);
});
================================================
FILE: design-patterns/Javascript/Behavioral Pattern/Visitor Design Pattern/visitor.js
================================================
// Visitor Interface
class ShapeVisitor {
visitCircle(circle) {
throw new Error(`This circle method should be overridden!`);
}
visitRectangle(rectangle) {
throw new Error(`This rectangke method should be overridden!`);
}
}
// Concrete visitor classes
class AreaVisitor extends ShapeVisitor {
visitCircle(circle) {
const area = Math.PI * circle.radius * circle.radius;
console.log(`Aread of circle: ${area}`);
}
visitRectangle(rectangle) {
const area = rectangle.width * rectangle.height;
console.log(`Area of rectangle: ${area}`);
}
}
class PerimeterVisitor extends ShapeVisitor {
visitCircle(circle) {
const perimeter = 2 * Math.PI * circle.radius;
console.log(`Perimeter of circle: ${perimeter}`);
}
visitRectangle(rectangle) {
const perimeter = 2 * (rectangle.width + rectangle.height);
console.log(`Perimeter of rectangle: ${perimeter}`);
}
}
module.exports = { AreaVisitor, PerimeterVisitor };
================================================
FILE: design-patterns/Javascript/Creational Pattern/AbstractFactory Design Pattern/abstract.js
================================================
// Abstract product
class Chair {
sitOn() {
throw new error("Sitting on chair");
}
}
class Sofa {
lieOn() {
throw new error("Lying on sofa");
}
}
// Concrete product for modernStyle
class ModernChair extends Chair {
sitOn() {
console.log("Sitting on modern chair");
}
}
class ModernSofa extends Sofa {
lieOn() {
console.log("Lying on modern sofa");
}
}
// Concrete product for classicStyle
class ClassicChair extends Chair {
sitOn() {
console.log("Sitting on classic chair");
}
}
class ClassicSofa extends Sofa {
lieOn() {
console.log("Lying on classic sofa");
}
}
// Abstract factory
class FurnitureFactory {
createChair() {
throw new error("Creating chair");
}
createSofa() {
throw new error("Creating sofa");
}
}
// Concrete factory for modernStyle
class ModernFurnitureFactory extends FurnitureFactory {
createChair() {
return new ModernChair();
}
createSofa() {
return new ModernSofa();
}
}
// Concrete factory for classicStyle
class ClassicFurnitureFactory extends FurnitureFactory {
createChair() {
return new ClassicChair();
}
createSofa() {
return new ClassicSofa();
}
}
module.exports = {
ModernFurnitureFactory,
ClassicFurnitureFactory,
};
================================================
FILE: design-patterns/Javascript/Creational Pattern/AbstractFactory Design Pattern/main.js
================================================
const {
ModernFurnitureFactory,
ClassicFurnitureFactory,
} = require("./abstract");
function createFurniture(factory) {
const chair = factory.createChair();
const sofa = factory.createSofa();
chair.sitOn();
sofa.lieOn();
}
// Use the Modern Furniture Factory
const modernFactory = new ModernFurnitureFactory();
createFurniture(modernFactory);
// Use the Victorian Furniture Factory
const classicFactory = new ClassicFurnitureFactory();
createFurniture(classicFactory);
================================================
FILE: design-patterns/Javascript/Creational Pattern/Builder Design Pattern/app.js
================================================
const ComputerBuilder = require("./computerBuilder");
const myComputer = new ComputerBuilder("Intel", "4GB")
.addStorage("1TB")
.addMoniter("LG")
.build(); // Finally build the computer
console.log(myComputer);
================================================
FILE: design-patterns/Javascript/Creational Pattern/Builder Design Pattern/computerBuilder.js
================================================
class Computer {
constructor(builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.hardDisk = builder.hardDisk;
this.moniter = builder.moniter;
}
}
class ComputerBuilder {
constructor(cpu, ram) {
this.cpu = cpu;
this.ram = ram;
}
// Methods with chaining
addStorage(hardDisk) {
this.hardDisk = hardDisk;
return this;
}
addMoniter(moniter) {
this.moniter = moniter;
return this;
}
build() {
return new Computer(this); // Pass the builder methods to the computer
}
}
module.exports = ComputerBuilder;
================================================
FILE: design-patterns/Javascript/Creational Pattern/Factory Design Pattern/factory.js
================================================
const { cheesePizza, pepperoniPizza } = require("./pizza");
class pizzaFactory {
static createPizza(pizzaType) {
if (pizzaType === "cheese") {
return new cheesePizza();
} else if (pizzaType === "pepperoni") {
return new pepperoniPizza();
} else {
throw new Error("Invalid pizza type");
}
}
}
module.exports = pizzaFactory;
================================================
FILE: design-patterns/Javascript/Creational Pattern/Factory Design Pattern/main.js
================================================
const pizzaFactory = require("./factory");
function main() {
const pizzaType = process.argv[2] || "cheese";
try {
const pizza = pizzaFactory.createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} catch (error) {
console.log(error.message);
}
}
main();
================================================
FILE: design-patterns/Javascript/Creational Pattern/Factory Design Pattern/pizza.js
================================================
class Pizza {
prepare() {
throw new error('Method "prepare()" must be implemented');
}
bake() {
console.log("Baking for 25 minutes");
}
cut() {
console.log("Cutting the pizza");
}
box() {
console.log("boxing the pizza");
}
}
class cheesePizza extends Pizza {
prepare() {
console.log("Preparing cheese pizza");
}
}
class pepperoniPizza extends Pizza {
prepare() {
console.log("Preparing pepperoni pizza");
}
}
module.exports = {
cheesePizza,
pepperoniPizza,
};
================================================
FILE: design-patterns/Javascript/Creational Pattern/Prototype Design Pattern/app.js
================================================
class Car{
constructor(model, year, color){
this.model = model;
this.year = year;
this.color = color;
}
clone(){ // Clone method to clone the current object
return new Car(this.model, this.year, this.color); // Return the new object with same properties
}
getDetails(){
return `Model: ${this.model}, Year: ${this.year}, Color: ${this.color}`
}
}
const prototypeCar = new Car("Mustang", 2019, "red");
const cloneCar1 = prototypeCar.clone(); // 1st clone
cloneCar1.color = "blue";
const cloneCar2 = prototypeCar.clone(); // 2nd clone
cloneCar2.color = "green";
console.log(prototypeCar.getDetails());
console.log(cloneCar1.getDetails());
console.log(cloneCar2.getDetails());
================================================
FILE: design-patterns/Javascript/Creational Pattern/Singleton Design Pattern/app.js
================================================
// Importing
const singleton = require("./singleton");
const Singleton1 = require("./singleton");
const Singleton2 = require("./singleton");
Singleton1.increment();
console.log(Singleton1.getData());
console.log(Singleton2.getData());
console.log(Singleton1 === Singleton2); // True
================================================
FILE: design-patterns/Javascript/Creational Pattern/Singleton Design Pattern/singleton.js
================================================
//Variable to hold the instance
let instance = null;
class Singleton {
constructor() {
if (instance) {
//check if instance already exists
return instance; //return existing instance
}
this.data = 0;
instance = this;
}
// Method to modify data
increment() {
this.data += 1;
}
// Method to get the current data
getData() {
return this.data;
}
}
module.exports = new Singleton();
================================================
FILE: design-patterns/Javascript/Structural Pattern/Adapter Design Pattern/adapter.js
================================================
// usbAdapter.js
// No need to import USB_A_Connector here
class USB_Adapter {
constructor(connector) {
this.connector = connector; // Store the USB-A connector instance
}
plugIn() {
return this.connector.connect(); // Use the method of the passed instances
}
}
module.exports = USB_Adapter;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Adapter Design Pattern/main.js
================================================
const USB_A_Connector = require("./usbA_connector");
const Adapter = require("./adapter");
// Creating instances for imported classes
const usbAConnector = new USB_A_Connector();
const adapter = new Adapter(usbAConnector);
console.log(adapter.plugIn());
================================================
FILE: design-patterns/Javascript/Structural Pattern/Adapter Design Pattern/usbA_connector.js
================================================
// USB A plug class
// Old system
class USB_A_Connector {
connect() {
return "USB-A connector connected";
}
}
module.exports = USB_A_Connector;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Adapter Design Pattern/usbC_device.js
================================================
// Device class to connect USB A cable
// New system
class USB_C_Device {
plugIn() {
return "USB C device connected";
}
}
module.exports = USB_C_Device;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Bridge Design Pattern/device.js
================================================
// Device.js
// The Device interface
class Device {
turnOn() {
throw new Error("Method 'turnOn()' must be implemented.");
}
turnOff() {
throw new Error("Method 'turnOff()' must be implemented.");
}
}
// Concrete class for TV
class TV extends Device {
turnOn() {
console.log("TV is now ON.");
}
turnOff() {
console.log("TV is now OFF.");
}
}
// Concrete class for Radio
class Radio extends Device {
turnOn() {
console.log("Radio is now ON.");
}
turnOff() {
console.log("Radio is now OFF.");
}
}
// Exporting the device classes
module.exports = {
TV,
Radio,
};
================================================
FILE: design-patterns/Javascript/Structural Pattern/Bridge Design Pattern/main.js
================================================
// main.js
const { TV, Radio } = require("./device");
const RemoteControl = require("./remoteControl");
// Creating instances of devices
const tv = new TV();
const radio = new Radio();
// Creating a remote control for the TV
const tvRemote = new RemoteControl(tv);
tvRemote.pressOn();
tvRemote.pressOff();
// Creating a remote control for the Radio
const radioRemote = new RemoteControl(radio);
radioRemote.pressOn();
radioRemote.pressOff();
================================================
FILE: design-patterns/Javascript/Structural Pattern/Bridge Design Pattern/remoteControl.js
================================================
// RemoteControl.js
class RemoteControl {
constructor(device) {
this.device = device; // This is the bridge to the device
}
pressOn() {
this.device.turnOn(); // Call the device's turnOn method
}
pressOff() {
this.device.turnOff(); // Call the device's turnOff method
}
}
module.exports = RemoteControl;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Composite Design Pattern/app.js
================================================
const File = require("./file");
const Folder = require("./folder");
// Let's create some files with random file extensions
const file1 = new File("File1.js");
const file2 = new File("File2.py");
const file3 = new File("File3.cpp");
const file4 = new File("File4.txt");
const file5 = new File("File5.docx");
const file6 = new File("File6.xlsx");
const file7 = new File("File7.pptx");
const file8 = new File("File8.pdf");
const file9 = new File("File9.png");
const file10 = new File("File10.jpg");
// Let's create a folder to add files
const folder1 = new Folder("Folder1");
folder1.add(file1);
folder1.add(file2);
folder1.add(file4);
const folder2 = new Folder("Folder2");
folder2.add(file3);
folder2.add(file8);
const folder3 = new Folder("Folder3");
folder3.add(file5);
folder3.add(file9);
folder3.add(file10);
const folder4 = new Folder("Folder4");
folder4.add(file6);
folder4.add(file7);
// Let's create a root folder
const rootFolder = new Folder("Root");
rootFolder.add(folder1);
rootFolder.add(folder2);
rootFolder.add(folder3);
rootFolder.add(folder4);
// Let's show the details from the root folder
rootFolder.showDetails();
================================================
FILE: design-patterns/Javascript/Structural Pattern/Composite Design Pattern/component.js
================================================
// Abstract Class or Component class
class Component {
showDetails() {
throw new error("This method is overriden by subclasses");
}
}
module.exports = Component;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Composite Design Pattern/file.js
================================================
const Component = require("./component");
class File extends Component {
constructor(name) {
super();
this.name = name;
}
showDetails() {
console.log(`File: ${this.name}`);
}
}
module.exports = File;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Composite Design Pattern/folder.js
================================================
const Component = require("./component");
// Composite: Folder that can hold files or other folders
class Folder extends Component {
constructor(name) {
super();
this.name = name;
this.files = [];
}
add(file) {
this.files.push(file);
}
showDetails() {
console.log(`Folder: ${this.name}`);
this.files.forEach((file) => file.showDetails());
}
}
module.exports = Folder;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Decorator Design Pattern/additional.js
================================================
// Additional behavior class
class Cream {
constructor(coffee) {
this.coffee = coffee;
}
cost() {
return this.coffee.cost() + 5; // Add cost of cream to the base coffee class
}
}
class Sugar {
constructor(coffee) {
this.coffee = coffee; // Store the coffee instance
}
cost() {
return this.coffee.cost() + 2; // Add cost of sugar to the base coffee class
}
}
class Ice{
constructor(coffee) {
this.coffee = coffee; // Store the coffee instance
}
cost() {
return this.coffee.cost() + 1; // Add cost of ice to the base coffee class
}
}
module.exports = {Cream, Sugar, Ice};
================================================
FILE: design-patterns/Javascript/Structural Pattern/Decorator Design Pattern/coffee.js
================================================
// Base class component
class Coffee {
cost() {
return 10; // Base price of coffee is 10
}
}
module.exports = Coffee;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Decorator Design Pattern/main.js
================================================
const Coffee = require("./coffee");
const {Cream, Sugar, Ice} = require("./additional");
// Create an instance of coffee
let myCoffee = new Coffee();
console.log(`Base amount: ${myCoffee.cost()}`); // Get base cost of coffee
myCoffee = new Sugar(myCoffee);
console.log(`Sugar amount: ${myCoffee.cost()}`); // Add cost of sugar
myCoffee = new Cream(myCoffee);
console.log(`Cream amount: ${myCoffee.cost()}`); // Add cost of cream
myCoffee = new Ice(myCoffee);
console.log(`Ice amount: ${myCoffee.cost()}`); // Add cost of ice
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/dvdPlayer.js
================================================
// Class for DVD player functionality
class DVDPlayer {
on() {
console.log("DVD player is on");
}
play(movie) {
console.log(`Playing ${movie}`);
}
off() {
console.log("DVD player is off");
}
}
module.exports = DVDPlayer;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/lights.js
================================================
// Class for lights functionality
class Lights {
on() {
console.log("Lights on, take you're seat!");
}
off() {
console.log("Lights off, get ready to see the show!");
}
}
module.exports = Lights;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/main.js
================================================
// client code for facade design pattern
const MovieFacade = require("./movieFacade");
const movieFacade = new MovieFacade();
// By getting the required data, we can proceed all the functionality using facade design pattern.
movieFacade.watchMovie("Goat 🍾🎉");
movieFacade.getSnacks("Popcorn");
movieFacade.endMovie();
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/movieFacade.js
================================================
const SoundSystem = require("./soundSystem");
const DVDPlayer = require("./dvdPlayer");
const Projector = require("./projector");
const Lights = require("./lights");
const Snacks = require("./snacks");
class MovieFacade {
constructor() {
this.soundSystem = new SoundSystem();
this.dvdPlayer = new DVDPlayer();
this.projector = new Projector();
this.lights = new Lights();
this.snacks = new Snacks();
}
watchMovie(movie) {
console.log(`Starting to watch a movie ${movie}`);
this.lights.on();
this.projector.on();
this.projector.connect("DVD Player");
this.dvdPlayer.on();
this.soundSystem.on();
this.dvdPlayer.play(movie);
this.soundSystem.setVolume("High");
}
getSnacks(snacks) {
console.log("1st part of the movie is great! Let's order some snacks");
this.snacks.noteOrder(snacks);
this.snacks.prepare();
this.snacks.serve(snacks);
}
endMovie() {
console.log("End of the movie, shutting down");
this.lights.off();
this.projector.off();
this.dvdPlayer.off();
this.soundSystem.off();
}
}
module.exports = MovieFacade;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/projector.js
================================================
// Class for projector functionality
class Projector {
on() {
console.log("Projector on");
}
connect(source) {
console.log(`Connecting projector to ${source}`);
}
off() {
console.log("Projector off");
}
}
module.exports = Projector;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/snacks.js
================================================
// Class for snacks functionality
class Snacks {
noteOrder(snacks) {
console.log(`Ordering ${snacks}`);
}
prepare() {
console.log("Preparing snacks 🍿");
}
serve(snacks) {
console.log(`Here is your ${snacks} sir!, enjoy your movie 😊`);
}
}
module.exports = Snacks;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Facade Design Pattern/soundSystem.js
================================================
// Class for sound system functionality
class SoundSystem {
on() {
console.log("Sound system is on");
}
setVolume(volume) {
console.log(`Setting volume to ${volume}`);
}
off() {
console.log("Sound system is off");
}
}
module.exports = SoundSystem;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Flyweight Design Pattern/circle.js
================================================
// Intrinsic state
class Circle{
constructor(color){
this.color = color;
}
draw(size, x, y){
console.log(`Drawing a circle of size ${size} at position (${x}, ${y})`);
}
}
module.exports = Circle;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Flyweight Design Pattern/circleFactory.js
================================================
// circleFactory.js
const Circle = require("./circle");
class CircleFactory {
constructor() {
this.circles = {}; // Store the created circles
}
getCircle(color) {
// Check if the circle exists
if (!this.circles[color]) {
// Create a new circle if it doesn't exist
this.circles[color] = new Circle(color);
}
return this.circles[color];
}
}
module.exports = CircleFactory;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Flyweight Design Pattern/main.js
================================================
const CircleFactory = require("./circleFactory");
const circleFactory = new CircleFactory();
const redCircle = circleFactory.getCircle("red");
redCircle.draw("big", 20, 30);
const blueCircle = circleFactory.getCircle("blue");
blueCircle.draw("medium", 200, 300);
const greenCircle = circleFactory.getCircle("red");
greenCircle.draw("medium", 200, 300); // Here it won't create a new object as it already exists.
console.log(
`Total unique circle instance created are: ${
Object.keys(circleFactory.circles).length
}`
);
================================================
FILE: design-patterns/Javascript/Structural Pattern/Proxy Design Pattern/main.js
================================================
const proxyImage = require("./proxyImage");
const image = new proxyImage("test.jpg");
console.log('First call to display:');
image.display();
console.log('Second call to display:');
image.display();
================================================
FILE: design-patterns/Javascript/Structural Pattern/Proxy Design Pattern/proxyImage.js
================================================
// Proxy object
const realImage = require("./real_Image");
class ProxyImage {
constructor(fileName) {
this.fileName = fileName;
this.realImage = null; // LAZY LOADING (Image not loaded yet)
}
display() {
// Loading the image only if requested
if (!this.realImage) {
this.realImage = new realImage(this.fileName);
}
this.realImage.display();
}
}
module.exports = ProxyImage;
================================================
FILE: design-patterns/Javascript/Structural Pattern/Proxy Design Pattern/real_Image.js
================================================
class realImage {
constructor(fileName) {
this.fileName = fileName;
this.loadFromDisk();
}
loadFromDisk() {
console.log(`Loading image from disk: ${this.fileName}`);
}
display() {
console.log(`Displaying image: ${this.fileName}`);
}
}
module.exports = realImage;
================================================
FILE: design-patterns/cpp/adapter/in_house_payment_processor.cpp
================================================
#include "in_house_payment_processor.h"
#include
#include
#include
void InHousePaymentProcessor::processPayment(double amount, const std::string& currency) {
std::cout << "InHousePaymentProcessor: Processing payment of " << amount << " " << currency << std::endl;
// Process payment logic
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::duration_cast(now.time_since_epoch());
transactionId = "TXN_" + std::to_string(now_ms.count());
isPaymentSuccessful = true;
std::cout << "InHousePaymentProcessor: Payment successful. Txn ID: " << transactionId << std::endl;
}
bool InHousePaymentProcessor::isPaymentSuccessful() {
return isPaymentSuccessful;
}
std::string InHousePaymentProcessor::getTransactionId() {
return transactionId;
}
================================================
FILE: design-patterns/cpp/adapter/in_house_payment_processor.h
================================================
#pragma once
#include "payment_processor.h"
#include
class InHousePaymentProcessor : public PaymentProcessor {
public:
void processPayment(double amount, const std::string& currency) override;
bool isPaymentSuccessful() override;
std::string getTransactionId() override;
private:
std::string transactionId;
bool isPaymentSuccessful = false;
};
================================================
FILE: design-patterns/cpp/adapter/legacy_gateway.cpp
================================================
#include "legacy_gateway.h"
#include
#include
void LegacyGateway::executeTransaction(double totalAmount, const std::string& currency) {
std::cout << "LegacyGateway: Executing transaction for " << currency << " " << totalAmount << std::endl;
auto now = std::chrono::high_resolution_clock::now();
transactionReference = now.time_since_epoch().count();
isPaymentSuccessful = true;
std::cout << "LegacyGateway: Transaction executed successfully. Txn ID: " << transactionReference << std::endl;
}
bool LegacyGateway::checkStatus(long transactionReference) {
std::cout << "LegacyGateway: Checking status for ref: " << transactionReference << std::endl;
return isPaymentSuccessful;
}
long LegacyGateway::getReferenceNumber() {
return transactionReference;
}
================================================
FILE: design-patterns/cpp/adapter/legacy_gateway.h
================================================
#pragma once
#include
class LegacyGateway {
public:
void executeTransaction(double totalAmount, const std::string& currency);
bool checkStatus(long transactionReference);
long getReferenceNumber();
private:
long transactionReference;
bool isPaymentSuccessful = false;
};
================================================
FILE: design-patterns/cpp/adapter/legacy_gateway_adapter.cpp
================================================
#include "legacy_gateway_adapter.h"
#include
LegacyGatewayAdapter::LegacyGatewayAdapter(LegacyGateway* legacyGateway)
: legacyGateway(legacyGateway) {}
void LegacyGatewayAdapter::processPayment(double amount, const std::string& currency) {
std::cout << "LegacyGatewayAdapter: Processing payment of " << amount << " " << currency << std::endl;
legacyGateway->executeTransaction(amount, currency);
std::cout << "LegacyGatewayAdapter: Payment processed successfully. Txn ID: "
<< legacyGateway->getReferenceNumber() << std::endl;
}
bool LegacyGatewayAdapter::isPaymentSuccessful() {
return legacyGateway->checkStatus(legacyGateway->getReferenceNumber());
}
std::string LegacyGatewayAdapter::getTransactionId() {
return std::to_string(legacyGateway->getReferenceNumber());
}
================================================
FILE: design-patterns/cpp/adapter/legacy_gateway_adapter.h
================================================
#pragma once
#include "payment_processor.h"
#include "legacy_gateway.h"
class LegacyGatewayAdapter : public PaymentProcessor {
public:
explicit LegacyGatewayAdapter(LegacyGateway* legacyGateway);
void processPayment(double amount, const std::string& currency) override;
bool isPaymentSuccessful() override;
std::string getTransactionId() override;
private:
LegacyGateway* legacyGateway;
};
================================================
FILE: design-patterns/cpp/adapter/main.cpp
================================================
#include "in_house_payment_processor.h"
#include "legacy_gateway.h"
#include "legacy_gateway_adapter.h"
#include
int main() {
std::cout << "Adapter Pattern Demo\n" << std::endl;
// Using the new payment processor
std::cout << "Using InHousePaymentProcessor:" << std::endl;
PaymentProcessor* processor = new InHousePaymentProcessor();
processor->processPayment(100.0, "USD");
std::cout << "Payment successful: " << (processor->isPaymentSuccessful() ? "Yes" : "No") << std::endl;
std::cout << "Transaction ID: " << processor->getTransactionId() << std::endl;
delete processor;
std::cout << "\nUsing LegacyGateway through adapter:" << std::endl;
LegacyGateway* legacyGateway = new LegacyGateway();
PaymentProcessor* adapter = new LegacyGatewayAdapter(legacyGateway);
adapter->processPayment(200.0, "EUR");
std::cout << "Payment successful: " << (adapter->isPaymentSuccessful() ? "Yes" : "No") << std::endl;
std::cout << "Transaction ID: " << adapter->getTransactionId() << std::endl;
delete adapter;
delete legacyGateway;
return 0;
}
================================================
FILE: design-patterns/cpp/adapter/payment_processor.h
================================================
#pragma once
#include
class PaymentProcessor {
public:
virtual ~PaymentProcessor() = default;
virtual void processPayment(double amount, const std::string& currency) = 0;
virtual bool isPaymentSuccessful() = 0;
virtual std::string getTransactionId() = 0;
};
================================================
FILE: design-patterns/cpp/bridge/circle.cpp
================================================
#include "circle.h"
Circle::Circle(Renderer* renderer, float radius)
: Shape(renderer), radius(radius) {}
void Circle::draw() {
renderer->renderCircle(radius);
}
================================================
FILE: design-patterns/cpp/bridge/circle.h
================================================
#pragma once
#include "shape.h"
class Circle : public Shape {
public:
Circle(Renderer* renderer, float radius);
void draw() override;
private:
float radius;
};
================================================
FILE: design-patterns/cpp/bridge/main.cpp
================================================
#include "vector_renderer.h"
#include "raster_renderer.h"
#include "circle.h"
#include "rectangle.h"
#include
int main() {
VectorRenderer vectorRenderer;
RasterRenderer rasterRenderer;
Circle vectorCircle(&vectorRenderer, 5.0f);
Rectangle vectorRectangle(&vectorRenderer, 4.0f, 3.0f);
Circle rasterCircle(&rasterRenderer, 7.0f);
Rectangle rasterRectangle(&rasterRenderer, 6.0f, 2.0f);
std::cout << "Vector Circle: ";
vectorCircle.draw();
std::cout << "Vector Rectangle: ";
vectorRectangle.draw();
std::cout << "Raster Circle: ";
rasterCircle.draw();
std::cout << "Raster Rectangle: ";
rasterRectangle.draw();
return 0;
}
================================================
FILE: design-patterns/cpp/bridge/raster_renderer.cpp
================================================
#include "raster_renderer.h"
#include
void RasterRenderer::renderCircle(float radius) {
std::cout << "Drawing circle as raster with radius: " << radius << std::endl;
}
void RasterRenderer::renderRectangle(float width, float height) {
std::cout << "Drawing rectangle as raster with width: " << width << ", height: " << height << std::endl;
}
================================================
FILE: design-patterns/cpp/bridge/raster_renderer.h
================================================
#pragma once
#include "renderer.h"
class RasterRenderer : public Renderer {
public:
void renderCircle(float radius) override;
void renderRectangle(float width, float height) override;
};
================================================
FILE: design-patterns/cpp/bridge/rectangle.cpp
================================================
#include "rectangle.h"
Rectangle::Rectangle(Renderer* renderer, float width, float height)
: Shape(renderer), width(width), height(height) {}
void Rectangle::draw() {
renderer->renderRectangle(width, height);
}
================================================
FILE: design-patterns/cpp/bridge/rectangle.h
================================================
#pragma once
#include "shape.h"
class Rectangle : public Shape {
public:
Rectangle(Renderer* renderer, float width, float height);
void draw() override;
private:
float width;
float height;
};
================================================
FILE: design-patterns/cpp/bridge/renderer.h
================================================
#pragma once
class Renderer {
public:
virtual ~Renderer() = default;
virtual void renderCircle(float radius) = 0;
virtual void renderRectangle(float width, float height) = 0;
};
================================================
FILE: design-patterns/cpp/bridge/shape.cpp
================================================
#include "shape.h"
Shape::Shape(Renderer* renderer) : renderer(renderer) {}
================================================
FILE: design-patterns/cpp/bridge/shape.h
================================================
#pragma once
#include "renderer.h"
class Shape {
protected:
Renderer* renderer;
public:
explicit Shape(Renderer* renderer);
virtual ~Shape() = default;
virtual void draw() = 0;
};
================================================
FILE: design-patterns/cpp/bridge/vector_renderer.cpp
================================================
================================================
FILE: design-patterns/cpp/bridge/vector_renderer.h
================================================
#pragma once
#include "renderer.h"
class VectorRenderer : public Renderer {
public:
void renderCircle(float radius) override;
void renderRectangle(float width, float height) override;
};
================================================
FILE: design-patterns/cpp/builder/http_request.cpp
================================================
================================================
FILE: design-patterns/cpp/builder/http_request.h
================================================
#pragma once
#include
#include