[디자인 패턴] - 옵저버 패턴

본 게시글은 '헤드퍼스트-디자인 패턴 (개정판)'을 기준으로 작성된 글입니다.

옵저버 패턴이란?

한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.

 

간단하게 말하면, 신문사와 구독자가 있을 때, 신문사를 주제 / 구독자를 옵저버라고 부른다.  

주제 객체는 주제에서 중요한 데이터를 관리하고, 옵저버 객체의 경우에는 주제를 구독하며, 주제의 데이터가 바뀔 때 마다 갱신 내용을 전달 받는다.

 

핵심은 1대다 이다.

어떤 객체가 변화할 때 이와 연관된 여러 객체에게 직접 통보하지 않고, 중간 관리자(옵저버)를 두어 변화의 감지와 통보를 대신하게 한다

옵저버 패턴은 다양한 방식으로 구현할 수 있다.

보통은 주제 인터페이스옵저버 인터페이스가 들어있는 클래스 디자인으로 구현한다.

 

옵저버 패턴 사용시 해소되는 SOLID 원칙

OCP, DIP, LSP

DIP :상위에서 하위로 의존성이 내려오는 것이 아니라 옵저버라는 인터페이스를 구현을 함으로써 반대로 바뀌게 된다. 업데이트가 되어도 하위에는 영향이 미치지 않는다.

 

예제

code : Observer.class

public class Observer {
    public String msg;
    public void receive(String msg)
    {
        System.out.println(this.msg + "에서 메세지를 받음 : " +msg);
    }
}

 

code : Notice.class

class Notice{
    private List<Observer> observers = new ArrayList<Observer>();
    public void attach(Observer observer)
    {
        observers.add(observer);
    }
    public void detach(Observer observer)
    {
        observers.remove(observer);
    }
    public void notifyObservers(String msg)
    {
        for(Observer o : observers){
            o.receive(msg);
        }
    }
}

옵저버를 등록하거나 해제하고 싶을 때는 attach(), detach() 메소드를 사용하면 된다. 

 

code : User1.class

public class User1 extends Observer{
    public User1(String msg)
    {
        this.msg = msg;
    }
}

Code : User2.class

public class User2 extends Observer{
    public User2(String msg)
    {
        this.msg = msg;
    }
}

Code : Main.class

public class Main {
    public static void main(String[] args)
    {
        Notice notice = new Notice();
        User1 user1 = new User1("유저1");
        User2 user2 = new User2("유저2");

        notice.attach(user1);
        notice.attach(user2);

        String msg = "공지사항";
        notice.notifyObservers(msg);

        notice.detach(user1);
        msg = "안녕";
        notice.notifyObservers(msg);
    }
}

 

Android에서의 Observer 패턴

안드로이드에서의 옵저버 패턴은, 데이터와 UI와의 상호작용에 있어서 간단하게 해준다.

주로 MVC(Model-View-Controller) 또는 MVVM(Model - View- ViewModel) 아키텍쳐에서 사용된다.

 

Jetpack 라이브러리의 LiveDataViewModel을 사용해서 옵저버 패턴을 구현할 수 있다.

 

간단하게 LiveData  ViewModel에 대해 설명하면,

  1. LiveData
    1. 데이터의 변화를 감지하고, 액티비티나 프래그먼트와 같은 라이프사이클을 가지는 구성요소에게 변경사항을 알려줄 수 있다.
    2. 데이터가 변경될 때마다 자동으로 업데이트 처리하여, 수동으로 관찰자에게 알릴 필요가 없다.
  2. ViewModel
    1. UI 관련 데이터를 저장하고 관리하는데 사용한다.
    2. UI와 데이터간의 분리를 통해 데이터 관리를 용이하게 한다.

 

아래의 예제 코드를 보면, data를 ViewModel에서 관리를 한다. 

data의 값이 바뀌게 되면, 변화를 관찰하여, 사용자가 정의한 코드가 실행된다. UI를 업데이트하거나, 데이터를 처리하는 등 다양한 작업을 할 수 있다.

 

아래의 코드에서 'newData''LiveData'가 가진 데이터의 변경 사항이다.

// ViewModel 클래스
public class MyViewModel extends ViewModel {
    private MutableLiveData<String> data = new MutableLiveData<>();

    public LiveData<String> getData() {
        return data;
    }

    public void updateData(String newData) {
        data.setValue(newData);
    }
}

// Activity나 Fragment에서 사용
public class MyActivity extends AppCompatActivity {
    private MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        viewModel = new ViewModelProvider(this).get(MyViewModel.class);

        viewModel.getData().observe(this, newData -> {
            // 데이터가 변경될 때마다 호출되는 코드
            // UI 업데이트 등을 수행
        });
    }
}

'디자인패턴' 카테고리의 다른 글

디자인 패턴 - 팩토리 패턴  (0) 2023.09.05
[디자인 패턴] - 데코레이터 패턴  (1) 2023.09.01
[디자인패턴] - 전략 패턴  (0) 2023.08.30