iegik
11/30/2017 - 10:33 AM

Design Patterns

Design Patterns in JavaScript

Strategy

Observer

Decorator

Factory

Factory method

Monad

function Maybe(val) {
    this.val = val || null;
}
Maybe.prototype.bind = function (f) {
    return (target => target(this.val))(f);
};
var x = (new Maybe(5));
var y = x
  .bind(v => new Maybe(v + 1))
  .bind(v => new Maybe(v * 2));
// --- Creational Patterns ---

// Singleton Pattern
// Ensures a class has only one instance and provides a global point of access.
interface Singleton {
    // The singleton instance might have methods or properties
    // operation(): void;
    // A static method to get the single instance is typical
    getInstance(): Singleton;
}

// Factory Method Pattern
// Defines an interface for creating objects, but lets subclasses alter the type of objects created.
interface Product {
    // Common interface for objects created by the factory
    use(): void;
}

interface Creator<P extends Product> {
    // The factory method - subclasses override this to return specific Product types (P)
    // factoryMethod(): P;
    // Creator's logic that uses the factory method
    // someOperation(): string;
}

// Abstract Factory Pattern
// Provides an interface for creating families of related or dependent objects
// without specifying their concrete classes.
// interface AbstractProductA {
//     // Interface for product A
//     usefulFunctionA(): string;
// }

// interface AbstractProductB {
//     // Interface for product B
//     usefulFunctionB(): string;
//     // Product B can collaborate with Product A
//     anotherUsefulFunctionB(collaborator: AbstractProductA): string;
// }

// interface AbstractFactory {
//     // Methods to create a family of products
//     createProductA(): AbstractProductA;
//     createProductB(): AbstractProductB;
// }

// Constructor Pattern
// A fundamental pattern using functions/classes to initialize objects.
// interface Person {
//     name: string;
//     age: number;
//     greet(): void;
// }

// Prototype Pattern
// Creates new objects by cloning an existing object (the prototype).
interface Prototype {
    // Method to clone the object
    clone(): Prototype;
}

// Builder Pattern
// Separates the construction of a complex object from its representation.
interface Builder<T extends string | string[] = string[], P extends ProductForBuilder = ProductForBuilder> {
    // Use a mapped type to define build methods based on the keys of T (if T is a string union)
    // or allow any string key if T is string[] or a general string.
    // This creates methods like buildPartA, buildPartB, etc.
    [K in T extends string ? `build${K}` : T extends string[] ? `build${T[number]}` : string]: () => void;

    // Method to get the final built object
    getProduct(): P;
    // Optional: Method to reset the builder for a new construction
    reset?(): void;
}

interface ProductForBuilder {
    // The complex object being built
    parts: string[];
}