Home > Web Front-end > JS Tutorial > Harnessing Functional Programming with JavaScript

Harnessing Functional Programming with JavaScript

Mary-Kate Olsen
Release: 2025-01-12 06:05:42
Original
838 people have browsed it

Design patterns are established solutions to frequent challenges in software design. By utilizing them, developers can enhance code readability, scalability, and maintainability. This article explores how TypeScript, an increasingly popular superset of JavaScript improves these patterns with its type safety and modern features. Whether you’re developing a large-scale application or a side project, grasping design patterns in TypeScript will boost your development skills.

What Are Design Patterns?

Design patterns are reusable, generic solutions to common challenges in software design. They aren't actual code but rather templates for addressing these issues. Originating from the "Gang of Four" (GoF) book, these patterns fall into three main categories:

  1. Creational Patterns: Concerned with the mechanisms of object creation.
  2. Structural Patterns: Emphasize the composition and organization of objects.
  3. Behavioral Patterns: Focus on the interactions and communication between objects.

Why Use Design Patterns in TypeScript?

TypeScript’s features make implementing design patterns more robust:

1. Static Typing: Errors are caught at compile time, reducing runtime bugs.
2. Interfaces and Generics: Allow more precise and flexible implementations.
3. Enum and Union Types: Simplify certain patterns, such as state management.
4. Enhanced Tooling: With IDE support, TypeScript boosts productivity.

Some Key Design Patterns in TypeScript

1. Singleton Pattern

Ensures that a class has only one instance and provides a global point of access to it.

Implementation in TypeScript:

class Singleton {
  private static instance: Singleton;

  private constructor() {} // Prevent instantiation

  public static getInstance(): Singleton {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
}

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
Copy after login
Copy after login

Use Case: Managing configuration settings or database connections.

2. Factory Pattern

Provides an interface for creating objects without specifying their exact classes.

Implementation:

interface Button {
  render(): void;
}

class WindowsButton implements Button {
  render() {
    console.log("Rendering Windows button");
  }
}

class MacButton implements Button {
  render() {
    console.log("Rendering Mac button");
  }
}

class ButtonFactory {
  static createButton(os: string): Button {
    if (os === "Windows") return new WindowsButton();
    if (os === "Mac") return new MacButton();
    throw new Error("Unknown OS");
  }
}

const button = ButtonFactory.createButton("Mac");
button.render(); // Output: Rendering Mac button
Copy after login

Use Case: UI frameworks for cross-platform applications.

3. Observer Pattern

Defines a one-to-many relationship, where changes in one object are notified to all its dependents.

Implementation:

class Subject {
  private observers: Array<() => void> = [];

  addObserver(observer: () => void) {
    this.observers.push(observer);
  }

  notifyObservers() {
    this.observers.forEach(observer => observer());
  }
}

const subject = new Subject();
subject.addObserver(() => console.log("Observer 1 notified!"));
subject.addObserver(() => console.log("Observer 2 notified!"));
subject.notifyObservers();
Copy after login

Use Case: Reactivity in front-end frameworks like Angular or React.

4. Strategy Pattern

Defines a family of algorithms, encapsulates each, and makes them interchangeable.

Implementation:

interface PaymentStrategy {
  pay(amount: number): void;
}

class CreditCardPayment implements PaymentStrategy {
  pay(amount: number) {
    console.log(`Paid ${amount} using Credit Card`);
  }
}

class PayPalPayment implements PaymentStrategy {
  pay(amount: number) {
    console.log(`Paid ${amount} using PayPal`);
  }
}

class PaymentContext {
  constructor(private strategy: PaymentStrategy) {}

  executePayment(amount: number) {
    this.strategy.pay(amount);
  }
}

const payment = new PaymentContext(new PayPalPayment());
payment.executePayment(100); // Paid 100 using PayPal
Copy after login

Use Case: Payment systems in e-commerce platforms.

5. Decorator Pattern

Adds new functionality to an object dynamically.

Implementation:

class Singleton {
  private static instance: Singleton;

  private constructor() {} // Prevent instantiation

  public static getInstance(): Singleton {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
}

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
Copy after login
Copy after login

Use Case: Adding features to a product in a shopping cart.

Design Patterns Table

Pattern Category Use Case Benefit
Singleton Creational Managing global state like configurations Guarantees single instance
Factory Creational UI components or APIs Decouples creation logic
Observer Behavioral Event systems in frameworks Simplifies communication
Strategy Behavioral Algorithm selection in runtime Enhances flexibility
Decorator Structural Extending class functionality Adds dynamic capabilities
Pattern

Category

Use Case

Benefit
Singleton Creational Managing global state like configurations Guarantees single instance
Factory Creational UI components or APIs Decouples creation logic
Observer Behavioral Event systems in frameworks Simplifies communication
Strategy Behavioral Algorithm selection in runtime Enhances flexibility
Decorator Structural Extending class functionality Adds dynamic capabilities
Best Practices for Implementing Design Patterns
1. Understand the Problem:
Don't complicate things with unnecessary patterns. 2. Combine Patterns: Consider using combinations such as Singleton with Factory.

3. Leverage TypeScript Features:
    Utilize interfaces, generics, and enums to make implementation easier.
  • 4. Write Tests: Ensure that the patterns function as intended. Additional Resources
  • হাতে কলমে জাভাস্ক্রিপ্ট by Junayed Ahmed

Refactoring to Patterns
by

Joshua Kerievsky


See you in the next article, lad! ?

Harnessing Functional Programming with JavaScript

My personal website: https://shafayet.zya.me
Bit windy, innit bruv???

The above is the detailed content of Harnessing Functional Programming with JavaScript. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template