관찰자 패턴(Observer Pattern)

최용국·2020년 3월 17일
0

디자인패턴

목록 보기
5/6

20-0317 Observer Pattern

코드를 짜다보면 객체의 상태를 변경할 때 의존성이 있는 객체들의 상태들 까지 변경되길 바랄 때가 있다. 대부분 그렇지 않겠지만 코드를 중복해서 짜는 경우가 있다면 옵저버 패턴을 이용하면 꽤 괜찮은 코드를 짤 수 있다.

다음 예제는 직원(Employee) 객체는 평가(Rating) 등급이 있고 평가 등급에 따라 급여(Salary)가 달라진다. 팀 별로 직원의 평가등급이 매겨지고 평가를 실행하면 평가에 맞는 상승률로 급여가 상승한다.

class EvaluationAttribute

public class EvaluationAttribute : Attribute
{
    public EvaluationAttribute(double ascentRate)
    {
        AscentRate = ascentRate;
    }

    public double AscentRate { get; private set; }

}

enum Evaluation

public enum Evaluation
{
    [EvaluationAttribute(15)]
    A,
    [EvaluationAttribute(10)]
    B,
    [EvaluationAttribute(7)]
    C,
    [EvaluationAttribute(5)]
    D,
    [EvaluationAttribute(3)]
    E,
    [EvaluationAttribute(0)]
    F
}

interface IEvaluation

public interface IEvaluation
{
    void DoEvaluation();
    void SetEvaluation(Evaluation evaluation);
}

class Team

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($"=================");
        }
    }
    
}

class Employee

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:#,###}";
    }
}

static class CommonController

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;
    }
}

Program

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();
    }
}

결과

profile
코딩합시다.

0개의 댓글