

Intent
Attach additional responsibilities to an object dynamically. Decorator provide a flexible alternative to subclassing for extending functionality
동적으로 객체에게 추가적인 책임을 부여한다. Decorator는 기능적 확장을 위한 Subclassing을 하기 위해 유연한 선택을 제공한다.
기존의 객체에서 새로운 기능을 추가 시키려면 어떻게 해야 할까? 클래스 레벨에서의 접근은 아마도 기존 객체를 수정하거나 기능을 추가시킨 클래스를 구현하여 추가 시킬 것이다. 기존 클래스를 수정하게 되면 당장은 편하게 될지는 몰라도 이후 확장성이나 수정의 가용성이 현저하게 떨어지게 되며 새로운 클래스를 구현하게 되면 가능한 모든 경우의 수를 고려하여 구현해야 하기 때문에 코딩의 압박이 가해진다. 이렇게 하고 싶으면 해라. 굳이 말리지는 않겠다. 하지만 실행중의 상황이라면 이야기가 달라진다. 코드의 수정도 불가 하고, 새로운 클래스 역시 추가가 불가능 하다. 이래서 나온 것이 Decorator Pattern이다 이름처럼 기존의 기능에 새로운 기능을 장식하듯이 기능을 추가시켜 새로운 객체를 생성하는 방식이다. 기존의 클래스를 그냥 두고 Decorator클래스를 만들어 새로운 기능을 추가 및 관리하게 만듦으로써 기존의 객체가 Decorator에 있는 기능들을 참조하여 새로운 객체를 생성할 수 있게 만드는 것이다. 기존의 객체는 새로운 기능들을 단일 리스트처럼 차례대로 기능들을 추가 시키면 된다.
Decorator의 구현 방법은 장식할 클래스와 Decorator클래스를 같은 기반 클래스에게 상속받아 생성 후 Decorator 클래스가 기반 클래스의 객체를 참조 할 수 있게 만들어 주면 된다. 추가될 기능들은 Decorator를 상속받아 구현해준다. 구현 시 생각할 부분은 Decorate클래스와 장식할 객체의 클래스의 인터페이스가 일치 해야 하는데 그 이유는 추가 기능들이 장식할 때 장식될 객체 위에 덮어 씌우는 식으로 되기 때문이다. 기반 클래스를 상속하는 이유도 그 때문이다. 추가기능이 단지 하나 밖에 없을 때는 굳이 Decorator의 추상화 클래스를 만들 필요가 없다. 그리고 가능하면 기반 클래스가 가볍게 하는 것이 좋다. 기반 클래스의 하위 클래스들이 상속으로 이루어지기 때문에 기반 클래스가 무거우면 자연스레 서브 클래스의 무게도 커지게 되므로 성능의 저하를 가지게 된다. 패턴을 채택 할 때 생각을 할 때 고려할 점을 객체의 수정의 위치이다. 객체의 겉을 수정하고 싶다면 Decorator 패턴을 사용 하지만 속을 수정한다면 Strategy 패턴을 선택하는 것이 좋다.
Decorator의 장단점을 살펴 보면 장점은 정적인 상속보다는 유연하다는 점과 계층 구조에서의 기능적 중복을 막을 수 있다라는 점이다. 상속을 이용한 기능의 추가는 각 기능의 추가시 새로운 클래스를 생성을 하게 되어서 프로그램의 컴플렉시티를 높이는 주요한 원인이 된다. 반면에 Decorator를 이용하게 되면 기능의 추가 및 삭제가 용이하고 실행시간에도 손쉽게 장식이 가능하다. Decorator 클래스가 추가할 기능들을 따로 관리 하므로 계층 구조에서 발생할 수 있는 객체에 불필요한 기능들을 상속하거나 확장할 필요성이 없어지게 된다.
단점으로는 Decorator 클래스가 비독립적이고 짜잘한 객체들을 많이 생성한다라는 점이다. Decorator 객체는 장식의 역할만 할뿐 독립적으로 어떠한 역할을 할 수 없다. Decorator 생성시 각 기능들을 개별적으로 구현을 하기 때문에 각 기능의 클래스들의 코드들이 분산되어 있어 디버깅할 때 어려울 수 있다.
그럼 Decorator패턴은 어디에 사용할까? 동적으로 다른 객체에 영향 없이 개별적인 객체에 기능들을 추가 하고 싶을 때 사용하거나 서브클래싱(상속)에 의한 확장이 불가능 할때나 서브클래싱할 때 서브 클래스의 수가 급격히 늘어날 때 사용 되며, 또 클래스의 정의가 숨겨져 있을 때 사용 가능하다
Tag : decorator, Design Pattern, GOF