Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern: Decorator Pattern #365

Closed
Tracked by #364 ...
fkdl0048 opened this issue Jul 7, 2023 · 1 comment
Closed
Tracked by #364 ...

Pattern: Decorator Pattern #365

fkdl0048 opened this issue Jul 7, 2023 · 1 comment
Assignees
Labels
StudyList It deals with the contents of the study.
Milestone

Comments

@fkdl0048
Copy link
Owner

fkdl0048 commented Jul 7, 2023

Decorator Pattern

데코레이터 패턴(Decorator pattern)이란 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴으로, 기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 유연한 대안이 될 수 있다.

최근 읽은 책에서 나온 패턴이였는데 Issue를 만들어두고 미루다 이제야 작성한다.

게임에서는 동작 관련 패턴이 가장 많이 사용되기도 하지만 상태, 전략과 같이 쓰면 좋은 패턴이라고 생각되어 정리한다.

간단하게 뱀서류 게임을 보면 전략 패턴과 데코레이터 패턴을 써서 제작하지 않았을까? 라는 생각을 종종 했는데 그거에 맞춰서 예제도 같이 만들어 봤다.

우선 뱀서는 기본 스킬에서 다른 스킬이 추가되고 해당 스킬들의 레벨을 올리면 더욱 다양해지는 형태이다.

사실 스킬 자체가 크게 변하지 않는다면 전략패턴이 맞는 것 같지만 레벨을 많이 올리면 스킬에 붙는 부과효과가 아이 다르다고 가정한다

예제

바로 예제를 먼저 보고 구조에 대해서 설명하는 순서로 진행

public interface ISkill
{
    void Use();
}
public class BaseSkill : ISkill
{
    public void Use()
    {
        System.Console.WriteLine("기본 스킬 사용");
    }
}
public abstract class SkillDecorator : ISkill
{
    private ISkill _skill;

    public SkillDecorator(ISkill skill)
    {
        _skill = skill;
    }

    public virtual void Use()
    {
        _skill.Use();
    }
}
public class LaserSkill : SkillDecorator
{
    public LaserSkill(ISkill skill) : base(skill)
    {
    }

    public override void Use()
    {
        base.Use();
        System.Console.WriteLine("레이저 스킬 사용");
    }
}
public class ComboSkill : SkillDecorator
{
    public ComboSkill(ISkill skill) : base(skill)
    {
    }

    public override void Use()
    {
        base.Use();
        System.Console.WriteLine("콤보 스킬 사용");
    }
}
public class Program
{
    public static void Main(string[] args)
    {
        ISkill baseSkill = new BaseSkill();
        baseSkill.Use();

        ISkill laserSkill = new LaserSkill(new BaseSkill());
        laserSkill.Use();

        ISkill comboSkill = new ComboSkill(new BaseSkill());
        comboSkill.Use();

        // ---

        ISkill totalSkill = new ComboSkill(new LaserSkill(new BaseSkill()));
        totalSkill.Use();
    }
}
기본 스킬 사용
기본 스킬 사용
레이저 스킬 사용
기본 스킬 사용
콤보 스킬 사용
기본 스킬 사용
레이저 스킬 사용
콤보 스킬 사용

코드 전문이긴 하지만 더 자세하게 보고 싶다면 Code Review 링크

설명

기본적인 기능에 추가(데코레이션)하는 다양한 종류의 추가적인 기능을 동적으로 조합할 수 있는 패턴이다.

ISkill 인터페이스는 스킬이 기본적으로 가져가는 인터페이스로 이를 DI로 주입받아서 사용하게 되는 추상클래스 SkillDecorator가 핵심이다.

이후 기본 스킬에 붙게 되는 Decorator들은 이 SkillDecorator를 상속받아서 구현하게 된다.

이 패턴을 사용하지 않는다면 이런 추가기능의 요구사항에 대해서 상속 구조를 복잡하게 가져가야 하기 때문에 유연성이 떨어지게 된다.

물론 지금 처럼 인터페이스를 제작해서 스킬안에 해당 인터페이스를 구성으로 들고 있게 할 수 있지만 해당 스킬에 대한 개수와 변경사항이 미지수이기 때문에 스킬 자체 클래스를 수정하게 되며 이는 SRP를 위반 그리고 나아가 해당 코드 자체의 변경이 많아지게 된다. (응집성 증가, 커플링 증가)

가장 좋은 점은 동적으로 행동 자체를 유연하게 추가할 수 있다는 점이다.

하지만 너무 많이 사용하게 되면 마찬가지로 복잡도가 많이 증가하게 될 수 있다.

지금 코드도 생성자 체이닝?을 통해 값을 할당하여 중간 객체는 중개자 정도로 사용되며 이는 코드 스멜이라고 생각된다.

그럼에도 매력적인 패턴이라 사용할 수 있을 땐 사용해도 좋을 것 같다.

@fkdl0048 fkdl0048 added this to the 2023 milestone Jul 7, 2023
@fkdl0048 fkdl0048 added this to Todo Jul 7, 2023
@github-project-automation github-project-automation bot moved this to Todo in Todo Jul 7, 2023
@fkdl0048 fkdl0048 moved this from Todo to In Progress in Todo Jul 7, 2023
@fkdl0048 fkdl0048 self-assigned this Jul 7, 2023
@fkdl0048 fkdl0048 added the StudyList It deals with the contents of the study. label Jul 7, 2023
@fkdl0048 fkdl0048 mentioned this issue Jul 7, 2023
6 tasks
@fkdl0048 fkdl0048 moved this from In Progress to Two-Week Plan in Todo Jul 17, 2023
@fkdl0048 fkdl0048 moved this from Two-Week Plan to In Progress in Todo Jul 25, 2023
@fkdl0048 fkdl0048 moved this from In Progress to Todo in Todo Jul 27, 2023
@fkdl0048 fkdl0048 moved this from Todo to In Progress in Todo Aug 1, 2023
@fkdl0048 fkdl0048 mentioned this issue Aug 1, 2023
6 tasks
@fkdl0048
Copy link
Owner Author

fkdl0048 commented Aug 3, 2023

내용 정리는 draft에서 정리 후, 블로그로 옮기기, 예제 코드는 CodeReview에서 작성 후 옮기기

@fkdl0048 fkdl0048 closed this as completed Aug 3, 2023
@github-project-automation github-project-automation bot moved this from In Progress to Done in Todo Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
StudyList It deals with the contents of the study.
Projects
Archived in project
Development

No branches or pull requests

1 participant