본문 바로가기
[ Program ]/C#

[C#]Observer Pattern(옵저버 패턴)

by 관이119 2012. 9. 17.

* Observer Pattern(옵저버 패턴)

- 한 객체가 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 일대다 방식의 패턴

* Observer Pattern(옵저버 패턴)의 구성

- Subject Interface

- Observer Interface

- Display Interface

기본적으로 3개의 인터페이스로 나누어 구현된다.

- Subject Interface

자료가 갱신되면 옵저버들에게 전송해주는 부분으로써 전송부분, 옵저버를 추가, 삭제 하는 총 3개의 메서드를 상속할 것이다.

- Observer Interface

옵저버들이 상속할 인터페이스로써 Subject 에서 주는 데이타를 받는 부분(Updata())을 상속하여 구현할 것이다.

- Display Interface

마지막으로 옵저버들이 받은 데이타를 화면에 출력해주는 인터페이스로써 옵저버들이 상속받아 사용할 부분이다.

위에 3개의 Interface만 보더라도 어떤 방식이구나.. 라고 대충 짐작이 갈것이다.

Subject에서 자료를 받아 뿌려주면 그걸 옵저버들이 받아 갱신하는 방식인데..

이번 옵저버는 딱히 떠오르는 게임쪽 아이디어가 생각이 나질 않는다..

그래서 우리 일상생활에서 항상 만지고 있는 핸드폰.. 시간을 업데이트 해주는 기지국(에서 해주는지는 잘 모르겠다)을

예를 들어 프로그래밍을 해보기로 했다..

예제내용 : kim, kkang, min, 3명의 옵저버들이 시간서버에서 데이타를 받아오는 프로그램을 짜보도록 한다.

Subject와 클레스를 상속받는 TimeData를 구현해 보자.

abstract class Subject
{
public abstract void inObserver(Observer o); //옵저버 추가 메서드
public abstract void outObserver(Observer o); //옵저버 삭제 메서드
public abstract void sendObserver(); //옵저버에게 데이타 전송
}

class TimeData : Subject
{
private int _Time; //시간 데이타
private ArrayList ObserverList; //옵저버들을 관리해줄 ArrayList

public TimeData()
{
ObserverList = new ArrayList();
}
public override void inObserver(Observer o) //옵저버 추가 메서드
{
ObserverList.Add(o);
}
public override void outObserver(Observer o) //옵저버 삭제 메서드
{
int i = ObserverList.IndexOf(o);

if (i >= 0) { ObserverList.Remove(i); }
}
public override void sendObserver() //옵저버에게 데이타 전송
{
foreach (Observer o in ObserverList)
{
o.Updata(_Time);
}
}
public void SetData(int temp) //변경된 데이타를 받는 메서드
{
_Time = temp;
sendObserver();
}
}

데이타를 전송해줄 클레스를 구현하였다..

이제 옵저버를 구현 할 차례다...

interface Observer //데이타를 업데이트 작업을 하는 인터페이스
{
void Updata(int tempTime);
}
interface Display //화면에 출력을 담당하는 인터페이스

{
void display();
}
class kim : Observer, Display // 위 옵저버, 디스플레이 두개의 인터페이스를 상속 받는다.
{
private int _time; //데이타를 저장할 변수
private Subject TimeData; //Subject에 등록, 삭제 할때 사용될 인스턴스


public kim(Subject temp) //생성자가 실행되면 자기자신을 Subject에 등록한다
{
this.TimeData = temp;
TimeData.inObserver(this);
}
public void Updata(int tempTime) //데이타를 받는다
{
_time = tempTime;
display();
}
public void display() //화면에 출력한다.
{
Console.WriteLine("KIM\t : "+_time.ToString());
}
}
class kkangs : Observer, Display
{
....

}
class min : Observer, Display
{
....

}

실행하기전에 앞서 의문점이 들었다.. 옵저버가 상속받는 인터페이스들을 구현을 하다보니 모두 다 중복되는 코드들이 대부분이였다.

두개의 인터페이스를 하나로 합쳐 추상클레스나 가상클레스로 사용하면 중복되는 코드들을 많이 없어질꺼 같은데..

만든사람이 이렇게 만든 이유가 있지 않을까... -_-;

이제 마지막으로 실행을 해보도록 하자.

테스트 클레스이다.

class Program
{
static void Main(string[] args)
{
TimeData timeData = new TimeData();

kim _kim = new kim(timeData);
kkangs _kkangs = new kkangs(timeData);
min _min = new min(timeData);

timeData.SetData(11);
timeData.SetData(12);
timeData.SetData(13);
}
}

실행결과

KIM : 11
KKANG : 11
MIN : 11
KIM : 12
KKANG : 12
MIN : 12
KIM : 13
KKANG : 13
MIN : 13

 

출처 - http://blog.naver.com/thread08/10047210666

 

댓글