Gözlemci(Observer) Tasarım Deseni

07-05-2014
Nedir?

Gözlemci(Observer) tasarım deseni, behavioral tasarım desenlerinden biridir. Nesneler arasında one-to-many ilişki sağlar. Bir nesne durumunu değiştirdiğinde, ona bağlı diğer tüm nesneler uyarılır ve otomatik olarak güncellenir.


Ne zaman Kullanılır?

Bir nesnenin durumunun değişmesi ile o nesneye bağlı diğer nesnelerin bu değişimi bilmesini istiyorsak, böyle durumlarda bu tasarım desenini kullanabiliriz.


Nasıl Kullanılır?

Öncelikle iki tane interface sınıfına ihtiyacımız vardır: Subject ve Observer. Subject interface sınıfı durumu değişecek nesneyi temsil ederken, Observer türünden olan nesneler ise Subject türündeki nesneyi gözlemleyecek ve bir değişiklik olduğu zaman uyarılacaktır. Yani burada Subject etkileyen nesneyi, Observer ise etkilenen nesneleri temsil eder.


Faydaları Nedir?

1. Loosely-coupled uygulamalar yapmayı sağlar. Subject ile Observer birbirleriyle loosely-coupled'tır.
2. Bir nesnenin birden çok nesneyi otomatik olarak etkilemesini istiyorsak bu tasarım desenini kullanabiliriz. Örneğin, uygulamamızda A ve B kısımları olsun. A kısmında anlık sıcaklığın gösterildiğini varsayalım. B kısmı ise sıcaklık 20 derecenin altında olduğu zaman yeşil bir ışık göstersin. B kısmının sıcaklık değişikliklerine tepki göstermesi için kendisini A kısmının dinleyicisi(listener) olarak kaydetmesi gerekir. Kaydettikten sonra her bir sıcaklık değişimini izleyerek yeşil ışık gösterip göstermeyeceğini otomatik olarak kontrol eder.


Gerekenler

Türü interface olan Subject ve Observer sınıfları
Tek bir tane somut Subject sınıfı.
En az iki tane somut Observer sınıfı.
Test sınıfı

Not: Observer tasarım deseni one-to-many prensibini uyguladığı için tek bir tane Subject olmalı, birden çok ise Observer sınıfı olmalıdır.


Örnek Kullanım Alanları

1. Model-View-Controller (MVC) frameworklerinde kullanılır. Observer Views'leri temsil ederken, Model ise Subject'i temsil eder.
2. java.util.EventListener sınıfının tüm implementasyonlarında kullanılır.
3. javax.servlet.http.HttpSessionBindingListener
4. javax.servlet.http.HttpSessionAttributeListener
5. javax.faces.event.PhaseListener


Örnek Uygulama

Observer Interface

public interface Observer {
    public void update(float temp, float humidity, float pressure);
}

Observer interface içerisinde sadece tek bir tane metod bulunması yeterlidir. Bizim örneğimizde update() isimli metod kullanıldı.

Subject Interface
public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

Subject interface içerisinde bulunan tüm metodlar zorunludur. Bunların dışında başka metodlar eklenebilir.

DisplayElement Interface
public interface DisplayElement {
    public void display();
}

Bu interface sınıfını kullanmak zorunlu değildir. Örneğimizde gerektiği için kullanıldı.

Somut Subject Sınıfı

public class WeatherData implements Subject {
    private ArrayList observers;
    private float temperature;
    private float humidity;
    private float pressure;
          
    public WeatherData() {
        observers = new ArrayList();
    }
          
    public void registerObserver(Observer o) {
        observers.add(o);
    }
          
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }
          
    public void notifyObservers() {
        for (int i = 0; i < observers.size(); i++) {
            Observer observer = (Observer)observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }
          
    public void measurementsChanged() {
        notifyObservers();
    }
          
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
          
    public float getTemperature() {
        return temperature;
    }
          
    public float getHumidity() {
        return humidity;
    }
          
    public float getPressure() {
        return pressure;
    }
}

WeatherData sınıfı Observer tasarım deseninde somut Subject sınıfını temsil eder.

Somut Observer Sınıfları

public class ForecastDisplay implements Observer, DisplayElement {
    private float currentPressure = 29.92f;  
    private float lastPressure;
    private WeatherData weatherData;
      
    public ForecastDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }
      
    public void update(float temp, float humidity, float pressure) {
                lastPressure = currentPressure;
        currentPressure = pressure;
      
        display();
    }
      
    public void display() {
        System.out.print("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } else if (currentPressure == lastPressure) {
            System.out.println("More of the same");
        } else if (currentPressure < lastPressure) {
            System.out.println("Watch out for cooler, rainy weather");
        }
    }
}

Somut Observer sınıfı. Görüldüğü gibi constructor parametre olarak somut Subject türünden bir nesne alıyor ve bu nesnenin registerObserver() metodunu kullanarak kendisini kaydediyor. update() metodunda ise Subject sınıfının yaptığı değişikliği alıyor ve işliyor.

public class StatisticsDisplay implements Observer, DisplayElement {
    private float maxTemp = 0.0f;
    private float minTemp = 200;
    private float tempSum= 0.0f;
    private int numReadings;
    private WeatherData weatherData;
      
    public StatisticsDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }
      
    public void update(float temp, float humidity, float pressure) {
        tempSum += temp;
        numReadings++;
      
        if (temp > maxTemp) {
            maxTemp = temp;
        }
       
        if (temp < minTemp) {
            minTemp = temp;
        }
      
        display();
    }
      
    public void display() {
        System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
            + "/" + maxTemp + "/" + minTemp);
    }
}

İkinci Somut Observer sınıfı.

Test Sınıfı

public class WeatherStation {
      
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
      
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
      
        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);
    }
}

Test sınıfı. Dikkat edersek, observer sınıflarından nesne yaratılırken, parametre olarak somut Subject sınıfı kullanıldı.

Örneğimizin UML Diagramı




Soyut Fabrika Tasarım Deseni'nin Şematik Gösterimi

© 2019 Tüm Hakları Saklıdır. Codesenior.COM