-
디자인패턴, Observer 옵저버기타 정보/디자인패턴 2022. 2. 11. 01:02반응형
Observer의 뜻
영어 사전으로 보면 다음의 뜻을 가진다.
영어사전
observer미국식[əb│zɜːrvə(r)]영국식[əb│zɜːvə(r)]명사- 1
보는 사람, 목격자
According to observers, the plane exploded shortly after take-off.
목격자들에 의하면 그 비행기는 이륙 직후에 폭발했다. - 2
(회의·수업 등의) 참관인[옵서버]
A team of British officials were sent as observers to the conference.
영국 공무원들 한 팀이 그 총회에 참관인으로 파견되었다. - 3
관찰자, 관측자
a royal observer
왕실 입회인
[네이버 영어사전에서 발췌]
Observer 패턴
Observer 패턴은 관찰자, 참관인을 뜻하는 패턴으로 객체의 상태 변화를 관찰하는 관찰자를 두어 객체 사이에 일 대 다의 의존 관계를 정의해 두고, 어떤 객체의 상태가 변할 때 그 객체에 의존성을 가진 다른 객체들이 그 변화를 통지받고 자동으로 갱신될 수 있게 만든다. 의존성을 가지는게 주요 특징이어서 Dependent(종속자)라고도 하고, 메인에 서브가 달라붙는 형식이기 때문에 Publish-Subscribe(발행-구독)라고도 한다.
즉, 관찰자 A에 객체B, C, D가 등록되고, B에서 id정보가 바뀌면 A를 통해 C, D에서도 id정보가 자동으로 업데이트되도록 구현하는 것이 옵저버 패턴이다.
구현
c#을 이용해 핵심만 구현해 보았다.
using TEST_Observer.Models; namespace TEST_Observer { public interface IObserver { void UpdateInfo(UserInfo userInfo); } public interface ISubject { void Attach(IObserver o); void Detach(IObserver o); void Notify(UserInfo userInfo); } }
[Observer 인터페이스]
using System.Collections.Generic; using TEST_Observer.Models; namespace TEST_Observer { public class Subject : ISubject { List<IObserver> observers = new List<IObserver>(); public void Notify(UserInfo userInfo) { foreach (IObserver o in observers) { o.UpdateInfo(userInfo); } } public void Attach(IObserver o) { observers.Add(o); } public void Detach(IObserver o) { observers.Remove(o); } } }
[관찰자 객체]
이 코드에서 핵심은 Observer가 수행할 인터페이스를 만든 후 관찰자 객체에서 해당 인터페이스를 사용하고, 옵저버에 등록 혹은 삭제, 알림 등 이벤트를 생성해주는 것이다.
C# Winform에서 구현 한 예제
IObserver, ISubject인터페이스는 위에 작성한 코드와 동일하다.
관찰자가 되는 메인이 되는 폼, Subject 클래스를 FormMain에서 다음과 같이 작성한다.
using System; using System.Collections.Generic; using System.Windows.Forms; using TEST_Observer.Models; namespace TEST_Observer { public partial class FormMain : Form, ISubject { List<IObserver> observers = new List<IObserver>(); public FormMain() { InitializeComponent(); } public void Notify(UserInfo userInfo) { foreach (IObserver o in observers) { o.UpdateInfo(userInfo); } } public void Attach(IObserver o) { observers.Add(o); } public void Detach(IObserver o) { observers.Remove(o); } private void buttonFormShow_Click(object sender, EventArgs e) { Form1 form1 = new Form1(this); form1.Show(); Form2 form2 = new Form2(this); form2.Show(); Form3 form3 = new Form3(this); form3.Show(); } } }
관찰 대상이 되는 폼, Form1, Form2, Form3의 코드는 다음과 같이 작성한다.
using System.Windows.Forms; using TEST_Observer.Models; namespace TEST_Observer { public partial class Form1 : Form, IObserver { ISubject subject; public Form1(ISubject _subject) { subject = _subject; subject.Attach(this); InitializeComponent(); } public void UpdateInfo(UserInfo userInfo) { labelUserName.Text = userInfo.UserName; } private void buttonUpdate_Click(object sender, System.EventArgs e) { UserInfo userInfo = new UserInfo(); userInfo.UserName = textBoxUserName.Text; subject.Notify(userInfo); } } }
using System.Windows.Forms; using TEST_Observer.Models; namespace TEST_Observer { public partial class Form2 : Form, IObserver { ISubject subject; public Form2(ISubject _subject) { subject = _subject; subject.Attach(this); InitializeComponent(); } public void UpdateInfo(UserInfo userInfo) { labelUserName.Text = userInfo.UserName; } private void buttonUpdate_Click(object sender, System.EventArgs e) { UserInfo userInfo = new UserInfo(); userInfo.UserName = textBoxUserName.Text; subject.Notify(userInfo); } } }
using System.Windows.Forms; using TEST_Observer.Models; namespace TEST_Observer { public partial class Form3 : Form, IObserver { ISubject subject; public Form3(ISubject _subject) { subject = _subject; subject.Attach(this); InitializeComponent(); } public void UpdateInfo(UserInfo userInfo) { labelUserName.Text = userInfo.UserName; } } }
Form1에서 UserName 텍스트박스에 값을 입력하고, 정보 수정 버튼을 클릭하면 Form1뿐만 아니라 Form2, Form3의 labelUserName도 똑같이 변경된다.
프로젝트 파일 첨부
참고 문헌
- GoF의 디자인패턴
참고 사이트
- 위키백과, 옵서버 패턴
- dofactory, C# Observer
- Refactoring.Guru, Observer in C#
반응형'기타 정보 > 디자인패턴' 카테고리의 다른 글
전략 패턴과 템플릿 메서드 패턴의 차이 (0) 2024.02.18 디자인패턴 자료는 리팩토링 구루에서! (0) 2022.12.12 - 1