Chain of Responsibility

Muzi·2023년 6월 3일
0

디자인 패턴

목록 보기
9/14

상황에 따라 요청을 처리할 객체가 변할 수 있는데 이런 상황에 사용하는 패턴
'요청하는 쪽'과 '처리하는 쪽'의 결합을 낮춘다

UML

Trouble class

: 발생한 문제

  • number - 발생한 트러블 번호

Support class

: 문제를 해결하는 추상 클래스

나머지 support class

: 문제를 해결하는 구현 클래스

  • 문제를 처리할 수 있으면 처리하고, 처리할 수 없으면 넘긴다
  • limit은 지정한 번호 미만의 트러블을 해결한다는 뜻

Class 설명

Trouble 클래스

  • 발생한 트러블 클래스
  • toString을 override해서 실행시 설정한 문자열로 출력함

@Getter
public class Trouble {

    // 트러블 번호
    private int number;

    public Trouble(int number) {
        this.number = number;
    }

	@Override
    public String toString() {
        return "[Trouble " + number + "]";
    }
}

Support 클래스

  • 문제 해결을 위한 클래스
  • 추상 클래스로 해당 클래스를 구현해 사용한다
@Setter
public abstract class Support {

    // 이 트러블 해결자의 이름
    private String name;
    // 다음 차례로 넘기는 곳
    private Support next;

    public Support(String name) {
        this.name = name;
    }

    // 문제 해결 절차
    public void support(Trouble trouble) {
        if (resolve(trouble)) { // 해결해보려한다
            done(trouble); // 해결했다
        } else if (next != null) { // 해결 못하는데 다음 해결클래스가 있으면
            next.support(trouble); // 처리를 떠넘긴다
        } else {
            fail(trouble); // 실패
        }
    }

	@Override
    public String toString() {
        return "[" + name + "]";
    }

    // 해결 방법
    protected abstract boolean resolve(Trouble trouble);

    // 해결
    protected void done(Trouble trouble) {
        System.out.println(trouble + " is resolved by " + this + ".");
    }

    // 미해결
    protected void fail(Trouble trouble) {
        System.out.println(trouble + " cannot be resolved.");
    }
}

NoSupport 클래스

  • 트러블 해결 자식 클래스
  • 항상 처리하지 않는다는 뜻
  • 떠넘기는걸 보여주기 위해서
public class NoSupport extends Support {

    public NoSupport(String name) {
        super(name);
    }

	@Override
    protected boolean resolve(Trouble trouble) {
        return false; // 자기는 문제 처리하지 않는다는 뜻
    }
}

LimitSupport 클래스

  • limit으로 지정한 번호 미만의 트러블만 해결하는 클래스
public class LimitSupport extends Support {

    private int limit; 

    public LimitSupport(String name, int limit) {
        super(name);
        this.limit = limit;
    }

    // limit 미만이면 해결 가능
    @Override
    protected boolean resolve(Trouble trouble) {
        if (trouble.getNumber() < limit) {
            return true;
        } else {
            return false;
        }
    }
}

OddSupport 클래스

  • 홀수 번호만 해결하는 클래스
public class OddSupport extends Support {

    public OddSupport(String name) {
        super(name);
    }

    // 홀수 번호라면 해결 가능
    @Override
    protected boolean resolve(Trouble trouble) {
        if (trouble.getNumber() % 2 == 1) {
            return true;
        } else {
            return false;
        }
    }
}

SpecialSupport 클래스

  • 지정한 번호의 문제를 해결하는 클래스
public class SpecialSupport extends Support {

    private int number;

    public SpecialSupport(String name, int number) {
        super(name);
        this.number = number;
    }

    // number와 같으면 해결 가능
    @Override
    protected boolean resolve(Trouble trouble) {
        if (trouble.getNumber() == number) {
            return true;
        } else {
            return false;
        }
    }
}

Main 클래스

  • support 클래스를 구현
  • 각 support클래스를 체이닝한다
  • 다양한 트러블을 일으킨다
  • 200이상의 트러블(429와 홀수번호를 제외한)은 아무도 처리 못함
public class Main {
    public static void main(String[] args) {

        Support alice = new NoSupport("Alice");
        Support bob = new LimitSupport("Bob", 100);
        Support charlie = new SpecialSupport("Charlie", 429);
        Support diana = new LimitSupport("Diana", 200);
        Support elmo = new OddSupport("Elmo");

        alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo);

        // 다양한 문제 발생
        for (int i = 0; i < 500; i += 33) {
            alice.support(new Trouble(i));
        }
    }
}

결론

  • 중요하다 생각하는건 결국 어떠한 요구에 대해서 하나의 클래스가 모두 책임을 진다는건 문제라는 것

  • 어떤 요구는 이 클래스가, 어떤 요구는 저 클래스가 이렇게 처리하는 클래스가 정해져있다는건 결국 요구하는 클라이언트가 처리하는 클래스들의 역할까지 알고있어야한다는 뜻 => 독립성이 훼손됨

  • 떠넘긴다는건 결국 자기 일에 집중할 수 있다는 뜻

  • 고정적인 일의 할당은 프로그램 실행 중 처리자 변경에 어렵다

  • 결국 처리를 넘긴다는 점에서 처리할 클래스가 이미 정해져있는 것과 비교했을때, 처리가 지연된다 볼 수 있다. -> 속도냐, 처리의 유연함이냐 trade of 문제

profile
좋아하는걸 열심히

0개의 댓글