본 게시글은 '헤드퍼스트-디자인 패턴 (개정판)'을 기준으로 작성된 글입니다.
옵저버 패턴이란?
한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.
간단하게 말하면, 신문사와 구독자가 있을 때, 신문사를 주제 / 구독자를 옵저버라고 부른다.
주제 객체는 주제에서 중요한 데이터를 관리하고, 옵저버 객체의 경우에는 주제를 구독하며, 주제의 데이터가 바뀔 때 마다 갱신 내용을 전달 받는다.
핵심은 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 라이브러리의 LiveData 와 ViewModel을 사용해서 옵저버 패턴을 구현할 수 있다.
간단하게 LiveData 와 ViewModel에 대해 설명하면,
- LiveData
- 데이터의 변화를 감지하고, 액티비티나 프래그먼트와 같은 라이프사이클을 가지는 구성요소에게 변경사항을 알려줄 수 있다.
- 데이터가 변경될 때마다 자동으로 업데이트 처리하여, 수동으로 관찰자에게 알릴 필요가 없다.
- ViewModel
- UI 관련 데이터를 저장하고 관리하는데 사용한다.
- 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 |