JAVA/Design_Pattern
[Design_Pattern] 데코레이터 패턴
realizers
2022. 3. 11. 22:18
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
반응형