Skip to content

Instantly share code, notes, and snippets.

@mattysmith22
Created June 1, 2019 18:38
Show Gist options
  • Save mattysmith22/f388ef5588b82afb0215bc7831a33467 to your computer and use it in GitHub Desktop.
Save mattysmith22/f388ef5588b82afb0215bc7831a33467 to your computer and use it in GitHub Desktop.

Observer pattern

The observer pattern is a design pattern useful when you need one object to be able to notify other objects about something occuring.

It works by having an observer interface that all objects that want to be notified of the event must implement, and then the notifier stores a list of the objects it needs to optimise. It then goes through this list of observers, notifying them using the given observers.

For my example, I will use an automatic checkout machine - after a transaction has been completed you need to make the balance change and print a receipt. First, let's build the interface they need to model:

observer.SaleObserver

package observer;

import java.util.ArrayList;

public interface SaleObserver {
    void notify(ArrayList<Product> products, int bankNum);
}

Then we can implement the simpler observing patterns.

observer.TransactionCompleter

package observer;

import java.util.ArrayList;

public class TransactionCompleter implements SaleObserver {
    public void notify(ArrayList<Product> products, int bankNum) {
        double total = 0;

        for(int i = 0; i < products.size(); i++)
            total += products.get(i).price;

        System.out.println("£" + total + " removed from bank account " + bankNum);
    }
}

observer.ReceiptPrinter

package observer;

import java.util.ArrayList;

public class ReceiptPrinter implements  SaleObserver {
    public void notify(ArrayList<Product> products, int bankNum) {
        double total = 0;

        System.out.println("BEGINNING OF RECEIPT");
        System.out.println("================================");

        for(int i = 0; i < products.size(); i++) {
            System.out.println("* " + products.get(i).name + " - £" + products.get(i).price);
            total += products.get(i).price;
        }
        System.out.println("");
        System.out.println("Total price: £" + total);

        System.out.println("================================");
        System.out.println("END OF RECEIPT");
    }
}

From here we can write the code for our checkout, paying specific attention to the addObserver function, along with notifyObservers.

package observer;

import java.util.ArrayList;

public class Checkout {
    private ArrayList<Product> cart;
    private ArrayList<SaleObserver> observers;

    public Checkout() {
       cart = new ArrayList<>();
       observers = new ArrayList<>();
    }

    public void addToCart(Product p) {
        cart.add(p);
    }

    public void pay(int bankNum) {
        notifyObservers(bankNum);
        cart.clear();
    }

    public void addObserver(SaleObserver o) {
        observers.add(o);
    }

    private void notifyObservers(int bankNum) {
        for(int i = 0; i < observers.size(); i++) {
            observers.get(i).notify(cart, bankNum);
        }
    }
}

And then just some test code to ensure it all works, that adds some stuff to the cart and pays.

package observer;

public class Main {
    public static void main(String[] args) {
        Checkout machine = new Checkout();

        machine.addObserver(new ReceiptPrinter());
        machine.addObserver(new TransactionCompleter());

        machine.addToCart(new Product("All day breakfast sandwich",1.50));
        machine.addToCart(new Product("Iced cappuchino",1.00));
        machine.addToCart(new Product("Kitkat",0.80));

        machine.pay(123456);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment