블링블링 범블링

옵저버 패턴(Observer Pattern) 본문

Technology/객체 지향 디자인 패턴

옵저버 패턴(Observer Pattern)

뻠스키 2018. 4. 18. 11:34

옵저버패턴(Observer Pattern)



한 객체의 상태가 변경되면 그 객체에 의존하는 다른 객체들 모두에게 알리고, 자동으로 내용이 갱신되는 패턴이다. 일방적인 통지 방식의 패턴이다. 한 객체의 상태변화를 다른 객체에게 통지할 수 있다.


옵저버패턴에는 크게 주제(Subject)객체와 옵저버(Observer) 객체가 존재한다. 주제객체는 옵저버의 목록을 관리하고 옵저버를 등록(attach)하고 제거(detach)하는 메서드를 제공한다. 그리고 상태의 변경이 일어나면 변경 내용을 알리는 메서드(notify())도 제공해 두 가지의 책임을 가지고 있다.


예시를 통해 옵저버패턴에 대해 더 자세히 알아보자. 보통 방송과 시청자를 통해서 옵저버패턴의 예시를 들고있다.  내가 만든 예시도 거기서 크게 벗어나지 않는다. 강의(Subject)가 있고 이 강의를 수강하는 학생들(Observers)이 있다고 하자. 학생들은 강의를 신청해 등록과 해지가 가능하고, 만약 강의가 오늘 시간날짜가 변경되는 경우에 내 강의를 수강하는 학생들에게 공지를 내릴 수 있다.


[클래스다이어그램]



[소스코드]


[Student : ObserverInterface]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface Observer {
    public void update(String name, String lecture);
    public String getName();
}
 
public class Student implements Observer{
     
    private String name;
    public Student(String name) {
        this.name = name;
    }
 
    @Override
    public void update(String name, String lecture_notify) {
        System.out.println(name + "에게 알립니다.");
        System.out.println(lecture_notify);
    }
     
    @Override
    public String getName() {
        return this.name;
    }
 
}

[Lecture : Subject]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface Subject_Lecture {
    public void add(Observer observer);
    public void delete(Observer observer);
    public void notifyObserver(String notify);
}
 
public class MathLecture implements Subject_Lecture{
    private ArrayList<observer> observers;
    private String lecture;
     
    public MathLecture(String name) {
        this.lecture = name;
        observers = new ArrayList<>();
    }
 
    @Override
    public void add(Observer observer) {
        observers.add(observer);
        System.out.println("강의 등록 : "+ observer.getName());
    }
 
    @Override
    public void delete(Observer observer) {
        observers.remove(observer);
        System.out.println("강의 취소 : "+ observer.getName());
    }
 
    @Override
    public void notifyObserver(String notify) {
        for(Observer observer : observers) {
            observer.update(observer.getName(),notify);
        }  
    }
     
}</observer>

[observerMain]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ObserverMain {
    public static void main(String[] args) {
         
        Subject_Lecture lecture = new MathLecture("math");
        Observer stu1 = new Student("문메이");
        Observer stu2 = new Student("문메라");
        Observer stu3 = new Student("라라");
         
        lecture.add(stu1);
        lecture.add(stu2);
         
        System.out.println("-------------------------------");
        lecture.notifyObserver("오늘 강의는 오후 1시에 진행됩니다");
 
        lecture.add(stu3);
        System.out.println("-------------------------------");
        lecture.notifyObserver("오늘 강의는 오후 5시에 진행됩니다");
         
        lecture.delete(stu1);
        lecture.delete(stu2);
        System.out.println("-------------------------------");
        lecture.notifyObserver("오늘 강의는 오후 5시에 진행됩니다");
         
    }
}

[출력화면]


출력화면을 통해서 특정 강의를 수강하는 학생들을 옵저버라고 했을 때 변경사항이 있을 때 내 강의를 듣는 모든 수강생(Observer)들에게 공지를 내릴 수 있다. 그리고, 예제에는 처리해주지 않았지만 각 학생들에게 상태 변화가 일어날 때 클래스를 변화시킬 수 있다.


하지만 옵저버패턴을 사용할 때 고려해야할 점이 몇가지가 존재한다. 

주제 객체의 통지 기능 실행하는 주체를 누구로 할 것인지에 따라 이점이 있어서 주제 객체의 상태가 자주 변경되는 경우에는 주제 객체에서 직접 통지 기능을 실행하는 것이 유리하다. 하지만 한 개 이상의 주제 객체의 연속적인 상태 변경 후에 옵저버에게 통지해야한다면 주제 객체의 상태를 변경하는 클래스에서 통지 기능을 실행해 주도록 구현하는 것이 통지 시점을 관리하기 좋다.

옵저버의 인터페이스 개수가 많을 때는 각각의 종류의 이벤트에 따라 옵저버 인터페이스를 분리해서 관리하는 것이 코드가 덜 복잡해진다.  


출처 위키디피아 옵저버패턴

출처 : http://meylady.tistory.com

Comments