Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions Creational/abstractFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// AbstractFactory interface
class AbstractFactory {
createProductA() {
throw new Error("This method should be overridden!");
}

createProductB() {
throw new Error("This method should be overridden!");
}
}

// Concrete Factories produce a family of products that belong to a single variant
class ConcreteFactory1 extends AbstractFactory {
createProductA() {
return new ConcreteProductA1();
}

createProductB() {
return new ConcreteProductB1();
}
}

class ConcreteFactory2 extends AbstractFactory {
createProductA() {
return new ConcreteProductA2();
}

createProductB() {
return new ConcreteProductB2();
}
}

// AbstractProductA interface
class AbstractProductA {
usefulFunctionA() {
throw new Error("This method should be overridden!");
}
}

// Concrete Products created by corresponding Concrete Factories
class ConcreteProductA1 extends AbstractProductA {
usefulFunctionA() {
return "The result of the product A1.";
}
}

class ConcreteProductA2 extends AbstractProductA {
usefulFunctionA() {
return "The result of the product A2.";
}
}

// AbstractProductB interface
class AbstractProductB {
usefulFunctionB() {
throw new Error("This method should be overridden!");
}

anotherUsefulFunctionB(collaborator) {
throw new Error("This method should be overridden!");
}
}

// Concrete Products created by corresponding Concrete Factories
class ConcreteProductB1 extends AbstractProductB {
usefulFunctionB() {
return "The result of the product B1.";
}

anotherUsefulFunctionB(collaborator) {
const result = collaborator.usefulFunctionA();
return `The result of the B1 collaborating with the (${result})`;
}
}

class ConcreteProductB2 extends AbstractProductB {
usefulFunctionB() {
return "The result of the product B2.";
}

anotherUsefulFunctionB(collaborator) {
const result = collaborator.usefulFunctionA();
return `The result of the B2 collaborating with the (${result})`;
}
}

// Client code works with factories and products through abstract types
function testFactory(factory) {
const productA = factory.createProductA();
const productB = factory.createProductB();

console.log(productB.usefulFunctionB());
console.log(productB.anotherUsefulFunctionB(productA));
}

// Testing the client code with the first factory type
console.log("Client: Testing client code with the first factory type...");
testFactory(new ConcreteFactory1());

// Testing the same client code with the second factory type
console.log(
"Client: Testing the same client code with the second factory type..."
);
testFactory(new ConcreteFactory2());

// Layout interface
class Layout {
getSize() {
throw new Error("This method should be overridden!");
}

getNavBar() {
throw new Error("This method should be overridden!");
}
}

// Concrete Layout classes
class WinLayout extends Layout {
getSize() {
return 8;
}

getNavBar() {
return "right";
}
}

class MacLayout extends Layout {
getSize() {
return 5;
}

getNavBar() {
return "left";
}
}

// Buttons interface
class Buttons {
getMinimizeLocation() {
throw new Error("This method should be overridden!");
}

getCloseLocation() {
throw new Error("This method should be overridden!");
}
}

// Concrete Button classes
class MacButtons extends Buttons {
getMinimizeLocation() {
return "leftTop";
}

getCloseLocation() {
return "leftTop";
}
}

class WinButtons extends Buttons {
getMinimizeLocation() {
return "rightTop";
}

getCloseLocation() {
return "rightTop";
}
}

// AbstractApp interface
class AbstractApp {
createLayout() {
throw new Error("This method should be overridden!");
}

createButtons() {
throw new Error("This method should be overridden!");
}
}

// Concrete App classes
class WindowsApp extends AbstractApp {
createLayout() {
return new WinLayout();
}

createButtons() {
return new WinButtons();
}
}

class MacApp extends AbstractApp {
createLayout() {
return new MacLayout();
}

createButtons() {
return new MacButtons();
}
}

// Client class using the abstract factory
class Client {
constructor(app) {
this.layout = app.createLayout();
this.buttons = app.createButtons();
}

openApp() {
console.log("I am able to open my app");
console.log(
"layout of my App \n Screen size : " +
this.layout.getSize() +
" , NavBar : " +
this.layout.getNavBar()
);
console.log(
"Buttons of my App \n minimize : " +
this.buttons.getMinimizeLocation() +
" , close : " +
this.buttons.getCloseLocation()
);
}
}

// Example usage
const client1 = new Client(new WindowsApp());
client1.openApp();
70 changes: 70 additions & 0 deletions Creational/singleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Define the main Singleton class
class Singleton {
static instance;

// Constructor should be private to prevent creating new instances with 'new'
constructor() {
if (Singleton.instance) {
// If an instance already exists, return it
return Singleton.instance;
}

// If no instance exists, set this as the new instance
Singleton.instance = this;

// Any custom properties or methods can be added here
this.foodLog = []; // Example property for logging information
}

// Public method to access the single instance of the class
static getInstance() {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}

// Business logic for logging, here we add an item to the food log
log(order) {
this.foodLog.push(order.foodItem);
console.log(`Logging order: ${order.foodItem}`);
}
}

// Test function to verify Singleton behavior
function clientCode() {
const logger1 = Singleton.getInstance();
const logger2 = Singleton.getInstance();

if (logger1 === logger2) {
console.log("Singleton works, both variables contain the same instance.");
} else {
console.log("Singleton failed, variables contain different instances.");
}
}

// Call the test function to verify
clientCode();

// Using the Singleton class within another class like Customer
class Customer {
constructor(order) {
this.price = order.price;
this.food = order.foodItem;
Singleton.getInstance().log(order); // Use the same Singleton instance to log
}
}

// Restaurant class using the same Singleton
class Restaurant {
constructor(inventory) {
this.quantity = inventory.count;
this.food = inventory.foodItem;
Singleton.getInstance().log(inventory); // Use the same Singleton instance to log
}
}

// Example usage of the classes
const customer1 = new Customer({ price: 20, foodItem: "Pizza" });
const restaurant1 = new Restaurant({ count: 5, foodItem: "Burger" });