Design Patterns in Java
Duration: 7 min
This module delves into the essential design patterns in Java, which are crucial for building robust, scalable, and maintainable software systems. Understanding these patterns will empower you to write cleaner, more efficient code and improve collaboration among development teams.
Singleton Pattern
Visual Guide: This module includes diagrams and flowcharts. Check the course materials for detailed visualizations.
The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. This is particularly useful when exactly one object is needed to coordinate actions across the system, such as a configuration manager or a connection pool.
public class SingletonExample {
private static SingletonExample instance = null;
private SingletonExample() {
// private constructor to prevent instantiation
}
public static synchronized SingletonExample getInstance() {
if (instance == null) {
instance = new SingletonExample();
}
return instance;
}
public void showMessage() {
System.out.println("Hello from Singleton Pattern");
}
}
Hello from Singleton PatternObserver Pattern
The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. This is particularly useful in event handling systems, where multiple components need to react to state changes in a central object.
import java.util.ArrayList;
import java.util.List;
// Subject interface
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// Concrete Subject
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
// Observer interface
interface Observer {
void update();
}
// Concrete Observer
class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subj) {
this.subject = subj;
subject.registerObserver(this);
}
@Override
public void update() {
System.out.println("Observer: Subject state changed to " + subject.getState());
}
}
// Client code
public class ObserverExample {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
new ConcreteObserver(subject);
new ConcreteObserver(subject);
subject.setState(10);
subject.setState(20);
}
}
💡 Tip: When implementing the Observer pattern, ensure that the notify method is called only when there are changes in the subject's state to avoid unnecessary updates.
❓ What is the primary purpose of the Singleton pattern?
❓ Which method is used in the Observer pattern to update observers?