데코레이터 패턴

·2022년 9월 6일

c++ 디자인 패턴

목록 보기
8/9

개념

: 실행 시간에 객체에 기능을 추가할 때 사용하는 패턴

알아야 할 점.

  • 구성 을 사용함.
  • 인자로 갱신된 객체의 주소를 전달해야 함.
  • 상속의 경우, 업캐스팅으로는 불가하는 문제가 있음.

왜 안되냐면?
right 생상자로 진입하는 순간 fire 의 가상 함수포인터는 right 로 지정되개 때문임
- 상속은 클래스의 기능을 추가하는 것임. 또 다른 객체를 생성하게 됨.

우주선을 통한 예제

  • 발사체(파란 색) 가 하나 있는 우주선이 있음.

  • 아이템을 획득해서 왼쪽에 미사일이 장착되었다고 하자.

problem

  • fire 기능이 있는 우주선 클래스를 만들고,
  • 우주선의 fire 기능을 그대로 이어 받으면서, 왼쪽 미사일을 발사하는 클래스
    를 만들어라.

가) 우주선은 그대로 진행 중에, 아이템을 획득 후에서 왼쪽 미사일을
발사할 수 있어야 함.

  • 1번) 해당 코드는 다른 leftMisile 객체가 생긴 것임.
  • 2번) 가상함수로도 처리할 수 있음.
    but , 오른쪽 미사일 장착 시는 어떻게 할 것인가?
    기존의 왼쪽 미사일도 발사해야 하는데...

-> 결과 : 상속을 통해서는 접근할 수 없음 / 업캐스팅으로 해결 불가함.

  • 상속은 객체의 기능을 추가하는 것이 아님.
    클래스의 기능을 추가하는 것임.

개념 : 기준이 되는 것을 구성에다 넣어주자.

1) 상속을 제거
2) 구성 포인터에 기본이 되는 것을 참조

  • 그림 1번
    : 기존 spase 객체를 그대로 유지하면서, left미사일만 장착함.

상속과 구성

  • 상속은 코드 작성시에 기능 추가됨.
  • 구성을 런타임 중에 기능 추가할 수 있음.

Right 미사일을 만들어보자.

: left 미사일까지도 유지가 되어야 하는데,
당연히 불가함.

  • 그림 : 불가함!

    1. 왜냐하면? spacseShip을 상속하지도 않았는데, 접근이 불가능하지.
    1. spaceShip, leftMissile, RightMissil 3개에
      모두 접근할 수 있는 기반 클래스를 만들어야 함.
    1. 그래야 업캐스팅하는 방식으로 모두 접근이 가능함!


  • 결과 : 실행 시간에 객체에 기능을 추가함.

코드 보완

: Left, Right에 구성을 만들어서 처리를 했는데,
이를 공통의 클래스를 상속해 보완할 수 있음.

  • 그림 : 구성으로 사용된 포인터를 제거함

최종 코드

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#include <map>

class Component
{
public : 
	virtual void fire() = 0;
	virtual ~Component() {}
};


class spaceShip : public Component
{
public : 
	virtual void fire()
	{
		cout << "=====" << endl;
	}
};

class IDecorator : public Component
{
	Component * craft;
public : 
	IDecorator(Component *p) : craft(p) {}
	void fire() { craft->fire();  }
};


class LeftMissile : public IDecorator
{
public : 
	LeftMissile(Component *obj) : IDecorator(obj){}

	virtual void fire()
	{
		IDecorator::fire();
		cout << ">>>>>" << endl;
	}
};

class RightMissile : public IDecorator
{
//private:
	//Component * s;
public:
	RightMissile(Component *obj) : IDecorator(obj) {}

	void fire()
	{
		IDecorator::fire();
		cout << "<<<<<" << endl;
	}
	
};

int main()
{
	spaceShip s;
	s.fire();

	LeftMissile l(&s);
	l.fire();

	RightMissile r(&l);
	r.fire();
}


profile
🔥🔥🔥

0개의 댓글