Computer Science

Decorator Pattern | 데코레이터 패턴

연_우리 2022. 8. 16. 21:22
반응형

목차

     

     

     

     

    어떤 상황에서 쓰일까?

    댓글 작성 서비스는 필터를 받아서 동작한다. 

    이때 공백을 자르는 필터가 있을 것이고, 어떤 문자열을 자르는 필터가 있을 것이다.

    문자열을 자르는 필터는 new Client(new SpamFilter()); 로 사용하고

    공백을 자르는 필터는 new Client(new TrimFilter()); 로 사용할 것이다.

     

    그렇다면 문자열과 공백 둘다 자르는 필터는 어떻게 만들 수 있을까??

    SpamAndTrimFilter? 

     

    여기서 필터의 기능이 더 추가된다면..?

    SpamAndTrimAnd...And....Filter..?

     

    각 필터들의 기능은 그대로 놔두면서, 런타임 시에 이 필터들이 조합되며 동작하게 할 수는 없을까??

     

     

     

    데코레이터 패턴이란?

    런타임에서 기존 코드를 변경하지 않으면서 부가적인 기능을 추가할 수 있는 패턴이다.

     

    런타임에서 유연하게 객체를 조립하여 사용할 수 있다!

     

     

     

    장점

    - 새로운 클래스를 만들지 않고 기존 기능을 조합할 수 있다

    - 컴파일 시점이 아닌 런타임에 동적으로 기능을 변경할 수 있다

     

     

    단점

    - 데코레이터 조립 코드가 복잡하다

     

     

     

    구현코드

    기존코드

    public class CommentService {
        public void addComment(String comment) {
            System.out.println(comment);
        }
    }
    -------------------------------------------------------------------
    public class TrimmingCommentService extends CommentService {
        @Override
        public void addComment(String comment) {
            super.addComment(trim(comment));
        }
    
        private String trim(String comment) {
            return comment.replace("...", "");
        }
    }
    -------------------------------------------------------------------
    public class SpamFilteringCommentService extends CommentService {
        @Override
        public void addComment(String comment) {
            boolean isSpam = isSpam(comment);
            if (!isSpam) {
                super.addComment(comment);
            }
        }
        private boolean isSpam(String comment) {
            return comment.contains("http");
        }
    }
    public class Client {
    
        private CommentService commentService;
    
        public Client(CommentService commentService) {
            this.commentService = commentService;
        }
    
        private void writeComment(String comment) {
            commentService.addComment(comment);
        }
    
        public static void main(String[] args) {
            Client client = new Client(new SpamFilteringCommentService());   //⭐
            client.writeComment("오징어게임");
            client.writeComment("보는게 하는거 보다 재밌을 수가 없지...");
            client.writeComment("http://whiteship.me");
        }
    
    }

    ⭐ 부분이 계속 변하게된다.

    스팸문자열을 거르고 싶다면 SpamFilter... 공백을 제거하고싶다면 TrimFilter가 동작되게 하고싶다!

     

     

     

    변경코드

    public interface CommentService {
        void addComment(String comment);
    }
    public class DefaultCommentService implements CommentService {
        @Override
        public void addComment(String comment) {
            System.out.println(comment);
        }
    }
    public class CommentDecorator implements CommentService {
    
        private CommentService commentService;
    
        public CommentDecorator(CommentService commentService) {
            this.commentService = commentService;
        }
    
        @Override
        public void addComment(String comment) {
            commentService.addComment(comment);
        }
    }
    public class SpamFilteringCommentDecorator extends CommentDecorator {
    
        public SpamFilteringCommentDecorator(CommentService commentService) {
            super(commentService);
        }
    
        @Override
        public void addComment(String comment) {
            if (isNotSpam(comment)) {
                super.addComment(comment);
            }
        }
    
        private boolean isNotSpam(String comment) {
            return !comment.contains("http");
        }
    }
    ------------------------------------------------------------------------
    public class TrimmingCommentDecorator extends CommentDecorator {
    
        public TrimmingCommentDecorator(CommentService commentService) {
            super(commentService);
        }
    
        @Override
        public void addComment(String comment) {
            super.addComment(trim(comment));
        }
    
        private String trim(String comment) {
            return comment.replace("...", "");
        }
    }
    public class App {
    
        private static boolean enabledSpamFilter = true;
    
        private static boolean enabledTrimming = true;
    
        public static void main(String[] args) {
            CommentService commentService = new DefaultCommentService();
    
            if (enabledSpamFilter) {
                commentService = new SpamFilteringCommentDecorator(commentService);
            }
    
            if (enabledTrimming) {
                commentService = new TrimmingCommentDecorator(commentService);
            }
    
            Client client = new Client(commentService);
            client.writeComment("오징어게임");
            client.writeComment("보는게 하는거 보다 재밌을 수가 없지...");
            client.writeComment("http://whiteship.me");
        }
    }

    DefaultCommentService -> CommentService

    CommentDecorator -> CommentService

    SpamFilter -> CommentDecorator

    TrimFilter -> CommentDecorator

     

    디폴트가 아닌 변경될 수 있는 서비스들이 들어오는 CommentDecorator를 생성하고

    CommentDecorator를 구현하는 필터들을 생성해서 런타임 시에 동적으로 적용될 수 있도록 하였다!

     

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기