옵져버(Observer) 패턴

기타 2016. 10. 13. 08:55
728x90

옵져버 패턴은 어떤 객체의 상태가 변하면 그 객체의 상태에 의존성을 가진 다른 객체들이 그 변화를 통지 받고 자동으로 업데이트하게 하는 패턴.

 

쉽게 말하면 (전파자 - 전파를 받는 자들 (일대다))의 관계로 한명이 여러명에게 전달을 하는 거다.

 

아래는 이해하기 쉽도록 스타크래프트의 마린의 상태를 예로 들어 옵져버 패턴을 적용해본 예시이다.

 

마린의 상태는 내가 보는 모니터의 메인화면과, 캐릭터의 상태창, 적의화면에 모두 동일하게 체력상태가 보여야 된다는 것이다.

 

마린의 체력 상태가 변경된다면 메인화면, 상태창, 적의화면이라는 전파를 받는 자들에게 상태를 업데이트하라고 명령을 하는것이다.

 

001.using System;

002.using System.Collections.Generic;
003.using System.Linq;
004.using System.Text;
005.
006.namespace Observer
007.{
008. class Program
009. {
010. static void Main(string[] args)
011. {
012.
013. Marine ourMarine = new Marine("아군 마린", 100);
014. ourMarine.Attach(new MainScreen());
015. ourMarine.Attach(new StatusScreen());
016. ourMarine.Attach(new EnemyScreen());
017.
018. ourMarine.Health = 60;
019. ourMarine.Health = 40;
020.
021. Console.ReadKey();
022. }
023.
024. abstract class Unit
025. {
026. private string name;
027. private int health;
028. private List<UnitViewer> unitViewers = new List<UnitViewer>();
029.
030. public Unit(string name, int health)
031. {
032. this.name = name;
033. this.health = health;
034. }
035.
036. public void Attach(UnitViewer investor)
037. {
038. unitViewers.Add(investor);
039. }
040.
041. public void Detach(UnitViewer investor)
042. {
043. unitViewers.Remove(investor);
044. }
045.
046. public void Notify()
047. {
048. foreach (UnitViewer unitviewr in unitViewers)
049. {
050. unitviewr.Update(this);
051. }
052. }
053.
054.
055. public int Health
056. {
057. get { return health; }
058. set
059. {
060. health = value;
061. Notify();
062. }
063. }
064.
065. public string Name
066. {
067. get { return name; }
068. }
069. }
070.
071. class Marine : Unit
072. {
073. public Marine(string name, int health)
074. : base(name, health)
075. {
076. }
077. }
078.
079.
080. interface UnitViewer
081. {
082. void Update(Unit unit);
083. }
084.
085.
086. class MainScreen : UnitViewer
087. {
088. private Unit unit;
089.
090. public void Update(Unit _unit)
091. {
092. this.unit = _unit;
093. Console.WriteLine("메인화면 {0} 상태 변경 : 체력 {1}", this.unit.Name, this.unit.Health.ToString());
094. }
095.
096. public Unit Unit
097. {
098. get { return unit; }
099. set { unit = value; }
100. }
101. }
102.
103. class StatusScreen : UnitViewer
104. {
105. private Unit unit;
106.
107. public void Update(Unit _unit)
108. {
109. this.unit = _unit;
110. Console.WriteLine("상태창 {0} 상태 변경 : 체력 {1}", this.unit.Name, this.unit.Health.ToString());
111. }
112.
113. public Unit Unit
114. {
115. get { return unit; }
116. set { unit = value; }
117. }
118. }
119.
120. class EnemyScreen : UnitViewer
121. {
122. private Unit unit;
123.
124. public void Update(Unit _unit)
125. {
126. this.unit = _unit;
127. Console.WriteLine("적 상태창 {0} 상태 변경 : 체력 {1}", this.unit.Name, this.unit.Health.ToString());
128. }
129.
130. public Unit Unit
131. {
132. get { return unit; }
133. set { unit = value; }
134. }
135. }
136. }
137.}

 

 

Marine 클래스는 Unit이라는 클래스를 상속받고 있고, Attach 메소드를 통해서 UnitViewer(메인화면), StatusScreen(상태창), EnemyScreen(적 상태창) 이 3개의 클래스들 즉 전파를 받을 자들을 등록한다.

 

위 3개의 클래스들은 UnitViewer라는 인터페이스를 상속받고 있고 인터페이스 안에 있는 Update 함수를 각 클래스들에 맞게 재정의 해주고 있다.

 

이제 마린의 체력 상태가 바뀌게 되면 체력 수치를 바꾸고 Notify 메소드를 통해 등록되어있는 전파자들에게 Update 함수를 실행하도록 한다.

 

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침