본문 바로가기

Pattern/GOF

구조패턴 - 데코레이션 패턴

반응형

1. 데코레이션 패턴이란?

데코레이터 패턴(Decorator pattern)이란 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴이다. 

요리를 만들 때 음식을 맛깔스럽게 만들기 위해 데코를 한다고 하는데 이와 같이 무언가를 첨가한다는 개념으로 이해하면 좋을 것 같다.

2. 언제 사용하는지?

기존 기능은 유지하면서 새로운 기능을 더해야 할 때 사용할 수 있다.물론 기존 클래스를 상속 받아 새로운 서브 클래스를 만들어도 되지만 기능을 조합해야 하는 상황이라면 데코레이션 패턴이 더 유리하다.

3. 샘플코드

Http 통신할 때 Request Parameter를 체크하는 서비스를 만든다는 가정으로 작성하였다.

ParamService

interface ParamService
{
    boolean checkParams(Hashtable<String, String> param);
}

먼저 파라미터를 체크하는 인터페이스를 작성한다.

 

DefaultParamService

public class DefaultParamService implements ParamService
{
    @Override
    public boolean checkParams(Hashtable<String, String> param)
    {
        return isEmpty(param);
    }

    private boolean isEmpty(Hashtable<String, String> param)
    {
        return param != null && param.size() != 0;
    }
}

ParamService를 구현한 DefaultParamService를 만들어 준다.

해당 클래스에는 optional하지 않은 기본 기능들을 구현하는 것이 좋다.

여기선 기본적인 널 체크 기능을 넣어주었다.

 

ParamDecorator

public class ParamDecorator implements ParamService
{
    private ParamService mParamService;

    public ParamDecorator(ParamService mParamService) {
        this.mParamService = mParamService;
    }

    @Override
    public boolean checkParams(Hashtable<String, String> param) {
        return mParamService.checkParams(param);
    }
}

 

 

ReplaceParamDecorator

public class ReplaceParamDecorator extends ParamDecorator
{

    public ReplaceParamDecorator(ParamService mParamService) {
        super(mParamService);
    }

    @Override
    public boolean checkParams(Hashtable<String, String> param) {
        checkParam(param);
        return super.checkParams(param);
    }

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

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

구체적인 기능을 담당하며 여기선 특수문자를 치환하는 역할을 담당하고 있다.

ParamDecorator 클래스를 상속 받았기 때문에 외부에서 서비스를 주입받아야 사용할 수 있다.

 

 

TrimparamDecorator

public class TrimParamDecorator extends ParamDecorator
{
    public TrimParamDecorator(ParamService mParamService) {
        super(mParamService);
    }

    @Override
    public boolean checkParams(Hashtable<String, String> param) {
        trimValue(param);
        return super.checkParams(param);
    }

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

ReplaceParamDecorator 클래스와 같이 구체적인 기능을 담당하며 파라미터의 공백을 없애준다.

 

 

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

        ParamService service = new DefaultParamService();
        service = new TrimParamDecorator(service);
        service = new ReplaceParamDecorator(service);
        service.checkParams(params);

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

 

 

 

위 코드처럼 데코레이션 패턴은 서비스의 기능을 확장 및 조합이 가능하기 때문에 클래스의 요소들을 계속해서 수정하면서 사용하는 구조가 필요한 상황에 유용하게 사용할 수 있다.

 

 

 

반응형

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

행위패턴 - 책임 연쇄 패턴  (0) 2022.05.31
구조패턴 - 프록시  (0) 2022.05.26
구조패턴 - 컴포짓패턴  (0) 2022.05.23
생성패턴 - 팩토리메서드  (0) 2022.05.11
생성패턴- 싱글톤  (0) 2022.05.09