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("<");
break;
case 62: // '>'
strBuff.append(">");
break;
case 38: // '&'
strBuff.append("&");
break;
case 34: // '"'
strBuff.append(""");
break;
case 39: // '\''
strBuff.append("'");
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 |