Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    [Behavioral] Observer

    Published Apr 19, 2022 [  DesignPattern  ]

    Real world example

    A good example would be the job seekers where they subscribe to some job posting site and they are notified whenever there is a matching job opportunity.

    In plain words

    Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified.

    Wikipedia says

    The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

    Programmatic example

    Translating our example from above. First of all we have job seekers that need to be notified for a job posting

    /**
     * The Observer interface declares the update method, used by subjects.
     */
    interface Observer {
        // Receive update from subject.
        update(jobPost: JobPost): void;
    }
    
    /**
     * The Subject interface declares a set of methods for managing subscribers.
     */
    interface Subject {
        // Attach an observer to the subject.
        attach(observer: Observer): void;
    
        // Detach an observer from the subject.
        detach(observer: Observer): void;
    
        // Notify all observers about an event.
        notify(jobPost: JobPost): void;
    }
    
    // this is just something we will use in the concrete subject
    class JobPost {
        protected title
    
        constructor(title: string) {
            this.title = title;
        }
    
        getTitle() {
            return this.title
        }
    }
    
    // this is our observer
    class JobSeeker implements Observer{
        protected name;
        protected msg: string;
    
        constructor(name: string) {
            this.name = name
        }
    
        update(job: JobPost) {
            this.msg = `Hi ${this.name}! New job posted: ${job.getTitle()}`
            console.log(this.msg)
        }
    
        getMsg(): string {
            return this.msg;
        }
    }
    

    Then we have our job postings to which the job seekers will subscribe

    // our subject
    class EmploymentAgency implements Subject{
        protected observers: JobSeeker[] = []
    
        notify (jobPosting: JobPost) {
            this.observers.forEach(observer => observer.update(jobPosting))
        }
    
        attach(jobSeeker: JobSeeker) {
            this.observers.push(jobSeeker)
        }
    
        addJob(jobPosting: JobPost) {
            this.notify(jobPosting)
        }
    }
    

    Then it can be used as

    test('test observer pattern', () => {
        const johnDoe = new JobSeeker('John Doe')
        const janeDoe = new JobSeeker('Jane Doe')
    
        const employmentAgency = new EmploymentAgency()
        employmentAgency.attach(janeDoe)
        employmentAgency.attach(johnDoe)
    
        employmentAgency.addJob(new JobPost('Software Engineer'))
    
        expect(johnDoe.getMsg()).toEqual('Hi John Doe! New job posted: Software Engineer')
        expect(janeDoe.getMsg()).toEqual('Hi Jane Doe! New job posted: Software Engineer')
    })
    

    References