Design Patterns in Java

In this exercise, you will explore and practice the most common **design patterns** in Java. You will learn to implement patterns such as **Singleton**, **Factory**, and **Observer**, which are essential for improving the structure, scalability, and maintainability of your Java applications. These patterns are essential in object-oriented programming because they help solve recurring design problems in an efficient and reusable way. Through detailed, practical examples, you will understand how to apply these patterns in real-world situations to create more robust and flexible solutions.

Topic

Advanced Algorithms and Optimizations

Java Exercise

In this exercise, you will create a Java program that implements several common design patterns in object-oriented programming. You'll use the **Singleton** pattern to ensure that only one instance of a class exists, the **Factory** pattern to create objects without specifying the object's exact class, and the **Observer** pattern to allow one object to notify other objects about state changes without tightly coupling the classes together.

Instructions:

  1. Implement the **Singleton** pattern for a class that should have only one instance throughout the application.
  2. Develop the **Factory** pattern by creating a common interface for creating different types of objects without the client knowing the exact class that will be instantiated.
  3. Implement the **Observer** pattern so that one object (the subject) automatically notifies observer objects when its state changes.
  4. Test each pattern by creating examples of objects that use each of these patterns. Design.

This exercise will help you understand how to use Design Patterns in Java to improve the structure of your applications and make them more scalable and maintainable.


// Singleton Pattern
class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void showMessage() {
        System.out.println("This is the Singleton pattern.");
    }
}

// Factory Pattern
interface Vehicle {
    void create();
}

class Car implements Vehicle {
    public void create() {
        System.out.println("Car created.");
    }
}

class Motorcycle implements Vehicle {
    public void create() {
        System.out.println("Motorcycle created.");
    }
}

class VehicleFactory {
    public static Vehicle createVehicle(String type) {
        if (type.equals("Car")) {
            return new Car();
        } else if (type.equals("Motorcycle")) {
            return new Motorcycle();
        }
        return null;
    }
}

// Observer Pattern
import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class Subject {
    private List observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " received the message: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        // Singleton
        Singleton singleton = Singleton.getInstance();
        singleton.showMessage();

        // Factory
        Vehicle car = VehicleFactory.createVehicle("Car");
        car.create();

        Vehicle motorcycle = VehicleFactory.createVehicle("Motorcycle");
        motorcycle.create();

        // Observer
        Subject subject = new Subject();
        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

        subject.addObserver(observer1);
        subject.addObserver(observer2);

        subject.notifyObservers("State changed.");
    }
}

 Output:

This is the Singleton pattern.
Car created.
Motorcycle created.
Observer 1 received the message: State changed.
Observer 2 received the message: State changed.

This code shows the implementation of the three Design Patterns in Java. The **Singleton** pattern ensures that only one instance of the class exists, the **Factory** pattern creates objects without specifying the specific class, and the **Observer** pattern allows observer objects to react to changes in the subject's state without being tightly coupled to each other.


 Share this JAVA exercise