본문 바로가기

Pattern/GOF

행위패턴 - 책임 연쇄 패턴

반응형

1. 책임 연쇄 패턴이란?

클라이언트로부터의 요청을 처리할 수 있는 처리객체를 집합(Chain)으로 만들어 부여함으로 결합을 느슨하기 위해 만들어진 디자인 패턴이다.

 

 

다음과 같은 상황일 때 책임 연쇄 패턴을 고려할 수 있다.

  • 요청의 발신자와 수신자를 분리하는 경우
  • 요청을 처리할 수 있는 객체가 여러개일 때 그 중 하나에 요청을 보내려는 경우
  • 코드에서 처리객체(handler)를 명시적으로 지정하고 싶지 않은 경우

 

2. 샘플 코드

구조 자체는 데코레이터 패턴과 비슷하기 때문에 데코레이터 패턴에서 사용했던 예제를 그대로 사용했다.

 

ParamHandler

public abstract class ParamHandler
{
    private ParamHandler mHandler = null;

    public ParamHandler(ParamHandler handler)
    {
        this.mHandler = handler;
    }

    public void checkParam(Hashtable<String, String> params)
    {
        if (mHandler != null)
        {
            mHandler.checkParam(params);
        }
    }
}

UML에서 Handler의 역할을 하는 추상클래스이다. 연쇄적인 처리를 가능하게 하는 핵심적인 클래스라고 볼 수 있다.

주의할 점은 체인의 끝지점에는 처리 객체가 null이기 때문에 꼭 null 체크를 해주어야 한다는 것이다.

 

ReplaceParamHandler

public class ReplaceParamHandler extends ParamHandler
{
    public ReplaceParamHandler(ParamHandler handler)
    {
        super(handler);
    }

    @Override
    public void checkParam(Hashtable<String, String> params)
    {
        params.replaceAll((k, v) -> v = filterSpcStrings(v));
        super.checkParam(params);
    }

    private String filterSpcStrings(String value)
    {
        StringBuffer strBuff = new StringBuffer();
        for (int i = 0; i < value.length(); i++)
        {
            char c = value.charAt(i);
            switch(value.charAt(i)){
                case 60: // '<'
                    strBuff.append("&lt;");
                    break;
                case 62: // '>'
                    strBuff.append("&gt;");
                    break;
                case 38: // '&'
                    strBuff.append("&amp;");
                    break;
                case 34: // '"'
                    strBuff.append("&quot;");
                    break;
                case 39: // '\''
                    strBuff.append("&apos;");
                    break;
                default:
                    strBuff.append(c);
                    break;
            }

        }
        return strBuff.toString();
    }
}

conCreateHandler의 역할을 하는 구현체이다.

인젝션 방어를 위해 주요 특수문자를 치환하는 기능을 담당하고 있다.

 

TrimParamHandler

public class TrimParamHandler extends ParamHandler
{
    public TrimParamHandler(ParamHandler handler) {
        super(handler);
    }

    @Override
    public void checkParam(Hashtable<String, String> params)
    {
        trimValue(params);
        super.checkParam(params);
    }

    private void trimValue(Hashtable<String, String> param)
    {
        param.replaceAll((k, v) -> v =
                v.trim());
    }
}

conCreateHandler의 역할을 하는 구현체이다.

파라미터 값들의 공백을 지워주는 역할을 한다.

 

Client

public class Client
{
    public static void main(String[] args)
    {
        Hashtable<String, String> params = new Hashtable<>();
        params.put("uid", "  55 ");
        params.put("title", "제목입니다.");
        params.put("contents", "select * from table where uid > 35");

        System.out.println("매개변수 필터링 전 : " + params.toString());

        ParamHandler service = new TrimParamHandler(
                new ReplaceParamHandler(null)
        );

        service.checkParam(params);

        System.out.println("매개변수 필터링 후 : " + params);
    }
}

 

결과

 

 

3. 장단점

1) 장점

  • 객체간의 결합도를 낮출 수 있다.
  • 처리 객체를 여러개 만들었을 때 순서를 바꾸거나 기능을 조합할 수 있다.

 

2) 단점

  • 디버깅할 때 확인해야 할 것 들이 많아진다 (처리 객체 순서, 처리 함수 호출 순서)
  • 연결 방식 때문에 런타임에 무한루프가 발생할 수 있다.

 

 

반응형

'Pattern > GOF' 카테고리의 다른 글

행위패턴 - 옵저버패턴  (0) 2022.06.09
구조패턴 - 프록시  (0) 2022.05.26
구조패턴 - 데코레이션 패턴  (0) 2022.05.24
구조패턴 - 컴포짓패턴  (0) 2022.05.23
생성패턴 - 팩토리메서드  (0) 2022.05.11