...

[Design Pattern/ JAVA ] 옵저버 패턴의 구현 (Observer) 본문

CS/디자인 패턴

[Design Pattern/ JAVA ] 옵저버 패턴의 구현 (Observer)

gi2 2022. 1. 3. 16:51

옵저버 패턴이란,

객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. [위키 백과] 

 

즉, 옵저버 패턴을 이용하면 별도의 함수 호출 없이 자동적으로 다른 객체의 상태 변화를 알 수 있다. 

 

[ 옵저버  패턴의 장점 ]

[1] 객체와 옵저버 객체 사이의 연결이 매우 느슨하다. 

맺고 끊기 쉬우며 서로가 서로에게 많은 영향을 주지 않는다.

따라서 시스템이 유연해지며 객체 간의 의존성을 제거할 수 있다. 

 

[2] 실시간으로 변경 사항을 옵저버들에게 전달할 수 있다.

 

 

예시를 들어서 설명해 보자.

 

 

어느 회사에 부서원 A,B,C가 있다고 하자. 

부서원들은 회사 내부의 변경 사항이 생길 때마다 즉시 이를 공지 받을 수 있다.

만약, 부서원 중 B가 갑작스럽게 퇴사하여 회사를 떠나게 되었다고 하자. 

이럴 경우, 더 이상 팀원 B는 회사로부터 공지 사항을 전달받지 못한다. 

 

가장 위에서 정의한 옵저버 패턴의 정의를 다시 살펴 보면,

옵저버 패턴 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.

 

위 예시를 통해 설명하면 객체는 회사가 되고

관찰자들(=옵저버)은 부서원들이 된다. 

회사는 옵저버들의 명단을 관리하여 공지 사항이 있을 때마다 명단에 있는 부서원들에게만 변경 사항을 알리고, 

부서원이 퇴사하면 명단에서 지워지게 되며, 신입사원이 들어온다면 명단에 새롭게 추가되게 된다. 

 

 


 

[ 옵저버 패턴의 구현 ]

 

연예인들이 팬들에게 1대 1 메세지를 전달하는 버블 어플을 간단하게 옵저버 패턴을 이용해서 구현해 보았다. 

팬들은 원하는 연예인을 선택하여 연예인들이 주는 연락을 받을 수 있다. 

구독이 끊어지면 더 이상 연락을 받지 못 한다. 

 

[ 전체 클래스 다이어그램

 

 

연예인 추상 인터페이스를 구현하고, 이를 상속 받는 지젤, 태연, 웬디 클래스를 구현하였다. (ㅎㅎ승완애리태연 사랑애)

그리고 옵저버 추상 인터페이스와 이를 상속받는 A,B를 구현하였다. 

비교를 위해 둘 다 태연을 구독하는 것으로 설정하였다. 

++DisplayMsg 인터페이스를 따로 두는 이유는 이를 상속받는 옵저버들의 함수 구현의 통일성을 주기 위함이다. 

 

(여러명 구독하는 건 나중에... 다시 구현해보려고 한다.,,, 귀차낭)

 

 

[ 코드 구현 ]

 

//Entertainer

public interface Entertainer {
    public void registerObserver(Observer observer);
    public void removeObeserver(Observer observer);
    public void notifyObserver();
}

//Wendy (태연, 지젤도 웬디와 동일)

import java.util.ArrayList;
import java.util.List;

public class Wendy implements Entertainer{

    private List<Observer> ObserverList;
    private List<String> MsgList;

    public Wendy()
    {
        ObserverList = new ArrayList<Observer>();
        MsgList = new ArrayList<String>();
    }
    @Override
    public void registerObserver(Observer observer) {
        ObserverList.add(observer);
    }

    @Override
    public void removeObeserver(Observer observer) {
        ObserverList.remove(observer);
    }

    @Override
    public void notifyObserver() {
        for (Observer observer : ObserverList){
            observer.update(MsgList);
        }
    }

    public void addMsg(String Msg){
        MsgList.add(Msg);
        notifyObserver();
    }
}

//Observer

import java.util.List;

public interface Observer {
    public void update(List<String> msg);
}

//DisplayMsg

public interface DisplayMsg {
    public void display();
}

//ObserverA (ObserverB와 동일)

import java.util.ArrayList;
import java.util.List;

public class ObserverA implements  Observer,DisplayMsg{
    private List<String> MsgList = new ArrayList<String>();
    private Taeyeon taeyeon;

    public ObserverA (Taeyeon taeyeon){
        this.taeyeon =taeyeon;
        taeyeon.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("ObserverA [메세지] 도착! ");
        for (String Msg :MsgList)
            System.out.println("[ "+Msg+" ]");
        System.out.println();
    }

    @Override
    public void update(List<String> msg) {
        this.MsgList.clear();
        for(String i : msg)
            this.MsgList.add(i);
        display();
    }
}

//Main

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

        ObserverA observerA = new ObserverA(taeyeon);
        ObserverB observerB = new ObserverB(taeyeon);
        
        //요기서 addMsg 하게 되면 ObserverA와 B에게 변경사항이 전달된다.
        taeyeon.addMsg("안녕하세여 태연입니다~ ");
        taeyeon.addMsg("ㅎㅎ");
        
        //태연의 Observer 리스트에서 B를 제거하였다.
        taeyeon.removeObeserver(observerB);
        
        //다시 Msg를 add하고 A와 B를 비교하여 본다.
        taeyeon.addMsg("ObserverB를 지웠어요ㅠ");
        observerB.display();
    }
}

 

[ 결과 확인

ObserverB를 태연의 옵저버 리스트에서 삭제한 이후엔 그 뒤에 추가된 Msg를 B가 확인할 수 없게 된다. 

 

 

끗!

Comments