Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Implementation of Observer Pattern for Object Interaction

Tech May 15 1

Observer Pattern Fundamentals

Observer pattern establishes dependency relationships between objects, enabling automatic notifications when one object changes state. The changing object (subject) automatical informs its dependent objects (observers), which then react accordingly. This pattern supports one-to-many relationships where subjects can manage multiple independant observers, allowing dynamic addition and removal for enhanced system extensibility.

The pattern is defined as: "Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically." Common aliases include Publish-Subscribe pattern, Model-View pattern, and Source-Listener pattern.

Pattern Structure


@startuml

abstract Publisher {
    + registerSubscriber(Subscriber s)
    + removeSubscriber(Subscriber s)
    + notifySubscribers()
}

note left of Publisher::notifySubscribers
for(Subscriber sub : subscribers) {
   sub.refresh();
}
end note

abstract Subscriber {
    + refresh()
}

class NewsPublisher extends Publisher {
    - latestUpdate
    + getUpdate()
    + setUpdate(String update)
}

class EmailSubscriber extends Subscriber {
    - currentStatus
    + refresh()
}

note right of EmailSubscriber::refresh
currentStatus = publisher.getUpdate();
end note
Publisher -right-> Subscriber: subscribers
EmailSubscriber -left-> NewsPublisher: publisher

@enduml

Structural Components

  • Publisher: Maintains subscriber collection and notification mechanism
  • NewsPublisher: Concrete implemantation containing state data
  • Subscriber: Interface declaring update method (refresh())
  • EmailSubscriber: Concrete implementation tracking publisher state

Java Implementation


import java.util.ArrayList;
import java.util.List;

public class ObserverImplementation {
    public static void main(String[] args) {
        NewsPublisher publisher = new NewsPublisher();
        new EmailSubscriber(publisher);
        SMSSubscriber smsSub = new SMSSubscriber(publisher);

        publisher.setUpdate("Breaking: System initialized");
        publisher.notifySubscribers();

        publisher.setUpdate("Update: New features deployed");
        publisher.notifySubscribers();
        
        publisher.removeSubscriber(smsSub);
        publisher.setUpdate("Final: Service termination notice");
        publisher.notifySubscribers();
    }

    abstract static class Publisher {
        protected List<subscriber> subscribers = new ArrayList<>();

        public void registerSubscriber(Subscriber s) {
            subscribers.add(s);
        }

        public void removeSubscriber(Subscriber s) {
            subscribers.remove(s);
        }

        public void notifySubscribers() {
            for (Subscriber s : subscribers) {
                s.refresh();
            }
        }
    }

    interface Subscriber {
        void refresh();
    }

    static class NewsPublisher extends Publisher {
        private String latestUpdate;

        public String getUpdate() {
            return latestUpdate;
        }

        public void setUpdate(String update) {
            this.latestUpdate = update;
        }
    }

    static class EmailSubscriber implements Subscriber {
        private NewsPublisher publisher;
        private String currentStatus;

        public EmailSubscriber(NewsPublisher publisher) {
            this.publisher = publisher;
            publisher.registerSubscriber(this);
        }

        @Override
        public void refresh() {
            currentStatus = publisher.getUpdate();
            System.out.println("Email Notification: " + currentStatus);
        }
    }

    static class SMSSubscriber implements Subscriber {
        private NewsPublisher publisher;
        private String currentStatus;

        public SMSSubscriber(NewsPublisher publisher) {
            this.publisher = publisher;
            publisher.registerSubscriber(this);
        }

        @Override
        public void refresh() {
            currentStatus = publisher.getUpdate();
            System.out.println("SMS Alert: " + currentStatus);
        }
    }
}
</subscriber>

Output Example


Email Notification: Breaking: System initialized
SMS Alert: Breaking: System initialized
Email Notification: Update: New features deployed
SMS Alert: Update: New features deployed
Email Notification: Final: Service termination notice

Advantages and Limitations

Benefits:

  • Decouples presentation layer from business logic
  • Establishes abstract publisher-subscriber relationship
  • Supports broadcast communication to multiple subscribers
  • Extensible without modifying existing code (OCP compliant)

Limitations:

  • Notification overhead with numerous subscribers
  • Potential circular dependency issues
  • No built-in mechanism to convey change causation

Use Cases

  • Model-view separation in GUI applications
  • Event-driven architectures
  • State synchronization across distributed components
  • Chained reaction systems (A → B → C)

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.