mardi 13 avril 2021

Oberserver design pattern: difference between notify and update

Hello I am trying to implement an analog clock using the Observer design pattern. I have understood the theory of how it works but when I was coding I couldn't understand the difference between notify and update, more specifically: when and where do we use notify versus when and where do we us update? They seem to have the same purpose of letting know the observes that something in the program has changed, but they do it differently, which is what I don't quite understand.

Also, I haven't understood very well where the addObserves method needs to be put in order for it to observe.

This is a piece of the code I have been trying to write, but I haven't been very successful.

I would be very grateful if someone could help me to finally fully understand this concept, which has me bothering me for some time!

ClockApp -> main class

package clock;

import clock.analog.AnalogClock;
import clock.timer.ClockTimer;

public class ClockApp {

    public ClockApp() {
        AnalogClock analogClock = new AnalogClock(timer);
        ClockTimer timer = new ClockTimer(analogClock);
        timer.start();
    }
    
    public static void main(String[] args) {
        new ClockApp();
    }
}

Clock Timer

package clock.timer;

import clock.ClockFrame;
import clock.Observable;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.logging.Logger;

public class ClockTimer extends Observable implements Runnable {
private long time;

private Calendar calendar;

private long delay = 1000;

private Thread thread;

private static Logger loggingService = Logger.getLogger("ClockTimer");

private ClockFrame clockFrame;

public ClockTimer(ClockFrame clockFrame){
    this.clockFrame = clockFrame;
    calendar = new GregorianCalendar();
}

private int getHour() {
    return calendar.get(Calendar.HOUR_OF_DAY);
}

private int getMinute() {
    return calendar.get(Calendar.MINUTE);
}

private int getSecond() {
    return calendar.get(Calendar.SECOND);
}

@Override
public void run() {
    while (thread != null) {
        try {
            time = System.currentTimeMillis();
            calendar.setTimeInMillis(time);

            notifyObservers(getHour());
            notifyObservers(getMinute());
            notifyObservers(getSecond());

            Thread.sleep(delay);
        } catch (InterruptedException e) {
            loggingService.severe("Timer got interrupted");
        }
    }

}

public void start() {
    if (thread == null) {
        thread = new Thread(this);
        thread.start();
    }
}

public void stop() {
    if (thread != null) {
        thread = null;
    }
}

}

Clock Frame

package clock;

import clock.analog.AnalogClock;
import clock.timer.ClockTimer;
import clock.util.PositionManager;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public abstract class ClockFrame extends JFrame implements Observer {

    private ClockTimer timer;
    private ClockPanel clockPanel;

    public ClockFrame(ClockTimer timer){
        super();
        this.timer = timer;

        setFrameTitle();
        addWindowListener(new DetachOnClosingWindowListener());

        clockPanel = createClockPanel();

        getContentPane().add(clockPanel, BorderLayout.CENTER);

        setLocation(PositionManager.getUniqueInstance().getClockWindowPosition());

        AlogClock analogClock = new AnalogClock(this.timer);
        timer.addObserver(analogClock);

        pack();
        setVisible(true);
    }

    protected abstract ClockPanel createClockPanel();

    public abstract void setFrameTitle();

    int hour;
    int minute;
    int second;

    @Override
    public void update(Observable o, Object arg) {
        clockPanel.displayTime(hour, minute, second);
    }

    private class DetachOnClosingWindowListener extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    }

}

Analog Clock

package clock.analog;

import clock.ClockFrame;
import clock.ClockPanel;
import clock.timer.ClockTimer;

import java.awt.*;

public class AnalogClock extends ClockFrame {

    private static final long serialVersionUID = 3544948857483180340L;

    public AnalogClock(ClockTimer timer) {
        super(timer);
    }

    protected ClockPanel createClockPanel(){
        AnalogClockPanel clockPanel = new AnalogClockPanel();
        clockPanel.setPreferredSize(new Dimension(400, 400));
        return clockPanel;
    }

    @Override
    public void setFrameTitle() {
        setTitle("Analog Clock");

    }
}

Aucun commentaire:

Enregistrer un commentaire