Learn
← Previous Next →

Hari 20: Design Patterns di JavaScript

60 min Last updated 09 Apr 2026

Observer Pattern

class EventEmitter {
    #listeners = new Map();

    on(event, listener) {
        if (!this.#listeners.has(event)) this.#listeners.set(event, []);
        this.#listeners.get(event).push(listener);
        return this; // chainable
    }

    off(event, listener) {
        const list = this.#listeners.get(event) || [];
        this.#listeners.set(event, list.filter(l => l !== listener));
    }

    emit(event, ...args) {
        (this.#listeners.get(event) || []).forEach(l => l(...args));
    }
}

const emitter = new EventEmitter();
emitter
    .on("data", d => console.log(`Data: ${d}`))
    .on("error", e => console.error(`Error: ${e}`));

emitter.emit("data", "Halo!");  // Data: Halo!
emitter.emit("error", "Oops"); // Error: Oops

Singleton Pattern

const Config = (() => {
    let instance;
    function createInstance() {
        return { theme: "dark", lang: "id", version: "1.0" };
    }
    return {
        getInstance: () => {
            if (!instance) instance = createInstance();
            return instance;
        }
    };
})();

const c1 = Config.getInstance();
const c2 = Config.getInstance();
console.log(c1 === c2); // true — sama instance

💡 Notice: Ini adalah implementasi mini Redux! dispatch menerima fungsi updater (reducer) yang menerima state lama dan return perubahan state.

Assignment

Implementasi State Manager sederhana menggunakan Observer pattern. Store menyimpan state, subscribe untuk listener, dispatch untuk update state.

Expected output:

State: {"counter":1,"nama":"App"}
State: {"counter":2,"nama":"App"}
State: {"counter":2,"nama":"My App"}
JS script.js
Solution
Output