시냅스

옵저버 패턴 Java로 구현 본문

디자인 패턴

옵저버 패턴 Java로 구현

ted k 2022. 8. 17. 14:59

옵저버 패턴 Observer Pattern

  • 객체 사이에 일대다의 의존 관계가 있고, 어떤 객체의 상태변하게 되면 그 객체에 의존성을 가진 다른 객체들이 변화의 통지(notify or update)를 받고 자동으로 갱신될 수 있게 함
  • dependent, publish-subscribe
  • 하나의 객체에 연동되는 여러 객체 집합이 있을 때 변화에 대한 일관성은 유지하고, 객체간의 결합도는 낮게하기 위한 패턴
  • 느슨한 결합 Loose coupling : 느슨하게 결합되어 있다는 것은 상호작용을 하지만 서로 잘 모른다는 것
  • 변화에 관심이 있는 객체에 대한 가정없이 통보될 수 있도록 해야 함
  • 주로 data - view 의 관계에서 사용됨
  • log와 handler들의 관계. (file, console, 등등)

 

 

  • Subject
    • Observer를 알고 있는 주체, Observer를 더하거나 뺄수 있음
  • Observer
    • Subject의 변화에 관심을 가지는 객체, 갱신에 필요한 인터페이스 정의, 객체들의 일관성을 유지
  • ConcreteSubject
    • ConcreteObserver에게 알려주어야하는 상태가 변경될때 통보 (주로 List로 Observer관리)
  • ConcreteObserver
    • 객체에 대한 참조자를 관리하고, Subject의 일관성 유지하며, Subject가 변경될 때 갱신되는 인터페이스 구현

 

결론

  • Subject와 Observer간의 추상적인 결합만의 존재
  • BroadCast 방식의 교류가 가능
  • 데이터와 뷰 사이에 자주 사용되는 방법

 

구현

package observer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

abstract class NumberGenerator { // subject
    private List<Observer> observers = new ArrayList<Observer>();
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
    public void deleteObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        Iterator<Observer> iterator = observers.iterator();
        while (iterator.hasNext()) {
            Observer o = iterator.next();
            o.update(this);
        }
    }

    public abstract int getNumber();
    public abstract void execute();
}

class RandomNumberGenerator extends NumberGenerator { // concrete subject
    private Random random = new Random();
    private int number;
    public int getNumber() {
        return number;
    }
    public void execute() {
        for (int i = 0; i < 20; i++) {
            number = random.nextInt(100);
            notifyObservers();
        }
    }
}

interface Observer { // observer
    public abstract void update(NumberGenerator generator);
}

class DigitObserver implements Observer { // concrete observer

    @Override
    public void update(NumberGenerator generator) {
        System.out.println("DigitObserver : " + generator.getNumber());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {

        }
    }
}

class GraphObserver implements Observer { // concrete observer

    @Override
    public void update(NumberGenerator generator) {
        System.out.println("GraphObserver : " + generator.getNumber());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {

        }
    }
}

public class ObserverImpl {
    public static void main(String[] args) {
        NumberGenerator generator = new RandomNumberGenerator();
        Observer observer1 = new DigitObserver();
        Observer observer2 = new GraphObserver();
        generator.addObserver(observer1);
        generator.addObserver(observer2);
        generator.execute();
    }
}

 

Comments