티스토리 뷰
728x90
반응형
데코레이터 패턴
- 데코레이터패턴은 객체의 결합을 통하여 기능을 동적으로 확장할 수 있도록 해주는 패턴입니다.
- 기본 기능에 추가할 수 있는 기능의 종류가 많은 경우 각 추가 기능을 Decorator 클래스로 정의한 후 필요한 Decorator 객체를 조합함으로써 추가 기능을 조합하는 설계 방식입니다.
클래스 다이어 그램
Component
- 기본 기능을 의미하는 ConcreteComponent와 추가 기능을 의미하는 Decorator의 공통 기능을 정의합니다.
- 클라이언트는 Component를 통해 실제 객체를 사용합니다.
ConcreteComponent
- 기본 기능을 구현하는 클래스
Decorator
- 다양한 추가 기능에 대한 공통 클래스를 정의합니다.
ConcreteDecorator
- Decorator 클래스의 하위 클래스로써 기본 기능에 추가되는 개별적인 기능을 의미합니다.
- ConcreteDecorator 클래스는 ConcreteComponent 객체에 대한 참조가 필요한데, 이는 Decorator 클래스에서 Component 클래스로의 합성 관계를 통해 표현됩니다.
예시
다양한 종류의 자동차 만들기
기본 기능을 하는 클래스
public class Car {
public void start() {
System.out.println("앞으로 출발합니다.");
}
public void stop() {
System.out.println("멈춥니다.");
}
public void back() {
System.out.println("후진합니다.");
}
}
추가 기능이 포함되어 있는 클래스
public class BusCar extends Car{
@Override
public void start() {
super.start();
}
@Override
public void stop() {
super.stop();
onTheBus();
}
@Override
public void back() {
super.back();
}
private void onTheBus() {
System.out.println("사람들이 버스에 탑승합니다.");
}
}
클라이언트
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.start(); // 앞으로 출발합니다.
Car bus = new BusCar();
bus.stop(); // 멈춥니다. + 사람들이 버스에 탑승합니다.
}
}
상황 : 여기서 다른 차종이 추가된다면?
- 다른 차종과 각 차종마다 기능이 다른 경우라면?
또하나의 추가 기능이 포함되어있는 클래스
public class SportCar extends Car{
@Override
public void start() {
super.start();
speed();
}
@Override
public void stop() {
super.stop();
}
@Override
public void back() {
super.back();
}
public void speed() {
System.out.println("속도를 높인다!");
}
}
클라이언트
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.start(); // 앞으로 출발합니다.
Car bus = new BusCar();
bus.stop(); // 멈춥니다. + 사람들이 버스에 탑승합니다.
Car sportCar = new SportCar();
sportCar.start(); // 앞으로 출발합니다. + 속도를 높인다!
}
}
문제점
- 각 기능의 종류와 추가 기능이 많아질 수록 클래스는 많아지게 됩니다.
해결책
- 해당 문제를 해결하기 위해서는 각 추가 기능별로 개별적인 클래스를 설계하고 기능을 조합할 때 각 클래스의 객체 조합을 이용합니다.
Component에 해당하는 클래스
- 공통 기능을 정의합니다.
public abstract class Component {
public abstract void start();
public abstract void stop();
public abstract void back();
}
ConcreteComponent
- 기본 기능을 구현하는 클래스를 정의합니다.
public class Car extends Component{
@Override
public void start() {
System.out.println("앞으로 출발합니다.");
}
@Override
public void stop() {
System.out.println("멈춥니다.");
}
@Override
public void back() {
System.out.println("후진합니다.");
}
}
Decorator
- 다양한 추가 기능에 대한 공통 클래스를 정의합니다.
public class CarDecorator extends Component{
private Component component;
public CarDecorator(Component component) {
this.component = component;
}
@Override
public void start() {
component.start();
}
@Override
public void stop() {
component.stop();
}
@Override
public void back() {
component.back();
}
}
ConcreteDecorator
- 개별 기능에 대한 클래스를 정의합니다.
// 버스
public class BusCar extends CarDecorator{
public BusCar(Component component) {
super(component);
}
@Override
public void start() {
super.start();
}
@Override
public void stop() {
super.stop();
onTheBus();
}
@Override
public void back() {
super.back();
}
private void onTheBus() {
System.out.println("사람들이 버스에 탑승합니다.");
}
}
// 스포츠카
public class SportCar extends CarDecorator{
public SportCar(Component component) {
super(component);
}
@Override
public void start() {
super.start();
speed();
}
@Override
public void stop() {
super.stop();
}
@Override
public void back() {
super.back();
}
public void speed() {
System.out.println("속도를 높입니다.");
}
}
// 트럭
public class TruckCar extends CarDecorator{
public TruckCar(Component component) {
super(component);
}
@Override
public void start() {
super.start();
}
@Override
public void stop() {
super.stop();
load();
}
@Override
public void back() {
super.back();
}
private void load() {
System.out.println("트럭에 짐을 실습니다.");
}
}
클라이언트
- 각 객체의 접근은 Component 클래스를 통해 이루어집니다.
- Component 클래스를 통해 이루어 진다면 어떤 기능을 추가하느냐에 관계없이 Client는 동일한 Component 클래스만을 통해 일관성 있는 방식으로 자동차에 대한 정보를 노출할 수 있습니다.
- Decorator 패턴을 사용한다면 각 기능별로 클래스를 구현할 필요가 없고 공통적인 부분을 도출하여 객체를 조합하게 된다면 효과적으로 설계를 할 수 있습니다.
public class Client {
public static void main(String[] args) {
Component car = new Car();
car.stop(); // 멈춥니다.
Component busCar = new BusCar(new Car());
busCar.stop(); // 멈춥니다. + 사람들이 버스에 탑승합니다.
Component truckCar = new TruckCar(new Car());
truckCar.stop(); // 멈춥니다. + 트럭에 짐을 실습니다.
Component sportCar = new SportCar(new Car());
sportCar.start(); // 앞으로 출발합니다. + 속도를 높입니다.
}
}
참고
https://gmlwjd9405.github.io/2018/07/09/decorator-pattern.html
https://readystory.tistory.com/195
728x90
반응형
'JAVA > Design_Pattern' 카테고리의 다른 글
[Design_Pattern] 프록시 패턴 (0) | 2022.03.23 |
---|---|
[Design_Pattern] 파사드 패턴 (1) | 2022.03.13 |
[Design_Pattern] 컴포지트 패턴 (0) | 2022.03.07 |
[Design_Pattern] 어댑터 패턴 (0) | 2022.03.05 |
[Design_Pattern] 싱글톤패턴 (0) | 2022.03.01 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- @ControllerAdvice
- spring boot excel download paging
- java userThread와 DaemonThread
- polling publisher spring boot
- 자바 백엔드 개발자 추천 도서
- pipeline architecture
- 레이어드 아키텍처란
- space based architecture
- java ThreadLocal
- spring boot excel download oom
- 트랜잭셔널 아웃박스 패턴 스프링부트
- pipe and filter architecture
- transactional outbox pattern spring boot
- microkernel architecture
- redis sorted set으로 대기열 구현
- redis 대기열 구현
- spring boot redis 대기열 구현
- JDK Dynamic Proxy와 CGLIB의 차이
- spring boot redisson 분산락 구현
- 서비스 기반 아키텍처
- redis sorted set
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- spring boot redisson destributed lock
- 람다 표현식
- service based architecture
- spring boot poi excel download
- spring boot 엑셀 다운로드
- spring boot redisson sorted set
- 공간 기반 아키텍처
- transactional outbox pattern
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함