코드를 짜다보면 객체의 상태를 변경할 때 의존성이 있는 객체들의 상태들 까지 변경되길 바랄 때가 있다. 대부분 그렇지 않겠지만 코드를 중복해서 짜는 경우가 있다면 옵저버 패턴을 이용하면 꽤 괜찮은 코드를 짤 수 있다.
다음 예제는 직원(Employee) 객체는 평가(Rating) 등급이 있고 평가 등급에 따라 급여(Salary)가 달라진다. 팀 별로 직원의 평가등급이 매겨지고 평가를 실행하면 평가에 맞는 상승률로 급여가 상승한다.
public class EvaluationAttribute : Attribute
{
public EvaluationAttribute(double ascentRate)
{
AscentRate = ascentRate;
}
public double AscentRate { get; private set; }
}
public enum Evaluation
{
[EvaluationAttribute(15)]
A,
[EvaluationAttribute(10)]
B,
[EvaluationAttribute(7)]
C,
[EvaluationAttribute(5)]
D,
[EvaluationAttribute(3)]
E,
[EvaluationAttribute(0)]
F
}
public interface IEvaluation
{
void DoEvaluation();
void SetEvaluation(Evaluation evaluation);
}
public class Team
{
private List<IEvaluation> Evaluations { get; set; } = new List<IEvaluation>();
public string Name { get; private set; }
public Evaluation _evaluation = Evaluation.F;
public Team(string name)
{
Name = name;
}
public Evaluation Evaluation
{
get
{
return _evaluation;
}
set
{
_evaluation = value;
foreach (var evaluation in Evaluations)
{
evaluation.SetEvaluation(_evaluation);
}
}
}
public void Attach(IEvaluation evaluation)
{
Evaluations.Add(evaluation);
}
public void Detach(IEvaluation evaluation)
{
Evaluations.Remove(evaluation);
}
public void DoEvaluation()
{
foreach (var evaluation in Evaluations)
{
evaluation.DoEvaluation();
}
}
public void Print()
{
foreach (var evaluation in Evaluations)
{
Console.WriteLine($"==={this.Name}===");
Console.WriteLine(evaluation);
Console.WriteLine($"=================");
}
}
}
public class Employee : IEvaluation
{
public Employee(string name, int salary)
{
Name = name;
Salary = salary;
}
public string Name { get; private set; }
public Evaluation Evaluation { get; private set; }
public int Salary { get; private set; }
public void DoEvaluation()
{
double ascentRate = CommonController.GetAsentRateFromEvaluation(this.Evaluation);
if (ascentRate == -1)
return;
Salary += (int)(Salary * (ascentRate / 100));
}
public void SetEvaluation(Evaluation evaluation)
{
this.Evaluation = evaluation;
}
public override string ToString()
{
return $"이름: {this.Name} 평가등급: {Evaluation} 급여: {Salary:#,###}";
}
}
public static class CommonController
{
internal static double GetAsentRateFromEvaluation(Evaluation evaluation)
{
EvaluationAttribute evaluationAttribute = null;
var evaluationType = typeof(Evaluation);
var evaluationMember = evaluationType.GetMember(evaluation.ToString());
evaluationAttribute = evaluationMember[0].GetCustomAttributes(typeof(EvaluationAttribute), false).FirstOrDefault() as EvaluationAttribute;
if (evaluationAttribute is null)
return -1;
return evaluationAttribute.AscentRate;
}
}
class Program
{
static void Main(string[] args)
{
Team DevelpoerTeam = new Team("개발팀");
DevelpoerTeam.Attach(new Employee("최용국", 40000000));
DevelpoerTeam.Attach(new Employee("도로시", 30000000));
Team DesignTeam = new Team("디자인팀");
DesignTeam.Attach(new Employee("이은혜", 37000000));
DesignTeam.Attach(new Employee("이정선", 33000000));
Team BuildingTeam = new Team("건축소방팀");
BuildingTeam.Attach(new Employee("안광필", 50000000));
DevelpoerTeam.Print();
DesignTeam.Print();
BuildingTeam.Print();
Console.WriteLine("===========================평가============================");
DevelpoerTeam.Evaluation = Evaluation.A;
DesignTeam.Evaluation = Evaluation.C;
BuildingTeam.Evaluation = Evaluation.E;
DevelpoerTeam.DoEvaluation();
DesignTeam.DoEvaluation();
BuildingTeam.DoEvaluation();
DevelpoerTeam.Print();
DesignTeam.Print();
BuildingTeam.Print();
Console.ReadLine();
}
}