재귀적 포함

EHminShoov2J·2024년 10월 9일
0

Design Pattern

목록 보기
3/6
post-thumbnail

1. Composite Pattern

1.1. 의도

  • 부분과 전체의 계층을 표현하기 위해 복합 객체를 트리 구조로 만들어낸다.
  • Composite 패턴을 클라이언트로 하려면 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 한다.
  • 재귀적, 혹은 당양한 타입의 함수 인자를 받기 위해서 공통의 interface로 묶어 Upcasting을 활용.

1.2. 예제

  • Pop Up Menu를 구현하고 싶은데, Pop up menu(Composite)는 menu(Leaf)도 들어가고 Pop up menu도 들어갈 수 있어야 한다.
  • 자기 자신을 받기 위해서는 단순히 Menu만 받아 저장하는 것이 아니라 Upcasting을 활용하여 BaseMenu(Component)를 받아서 저장하게 한다. -

1.3. 장점

  • 객체간의 관계만 바꾸어주면 수정과 추가가 쉽다
  • 위 그림의 색상 변경을 해상도 변경 아래 를 수정하기 위해서 아래와 같이 관계를 재설정 하여 구현 가능
int main()
{
	PopupMenu* root = new PopupMenu("ROOT");
	PopupMenu* pm1 = new PopupMenu("해상도 변경");
	PopupMenu* pm2 = new PopupMenu("색상 변경");

	root->add_menu(pm1);
//	root->add_menu(pm2); // 기존 관계 해지
	pm1->add_menu(pm2); // 새로운 관계 생성 

	pm1->add_menu(new MenuItem("HD", 11));
	pm1->add_menu(new MenuItem("FHD", 12));
	pm1->add_menu(new MenuItem("UHD", 13));

	pm2->add_menu(new MenuItem("RED",   21));
	pm2->add_menu(new MenuItem("GREEN", 22));
	pm2->add_menu(new MenuItem("BLUE",  23));
	pm2->add_menu(new MenuItem("BLACK", 24));

	// 메뉴를 시작하려면 ??
	root->command();
}
  • 공통 기능을 구현하는데 있어 두가지 방법을 따를 수 있음. 아래의 방법의 경우 복합객체와 객체의 사용법이 동일해진다는 장점이 존재한다.(단 Leaf 노드에서는 사용할 필요가 없기 때문에 Composite에서 기본적으로 재구현 하지 않으면 오류를 발생시키도록 설정해두는 방법도 존재)

    객체 지향이란 결국 객체를 만들고, 관계를 설정하고, 서로간의 메시지를 주고 받는(맴버 함수 호출) 과정이다.

2. Decorator Pattern

2.1. 의도

  • 객체에 동적으로 서비스를 추가할 수 있게 한다.
  • 객체에 서비스를 중첩적으로 추가할 수 있다.
  • 상속을 사용하여 서비스를 추가하는 것보다 포함을 사용하여 유연한 방법으로 서비스를 추가할 수 있다.
  • Component에 포함되는 다른 추가적인 ConreteComponet가 Decorator를
    재사용
    할 수 있다.

2.2 예제

  • Image 클래스는 draw() 함수를 보유하며, 이미지 파일을 출력하는 기능을 가지고 있다고 하자.
  • 하지만 이때 Image 클래스에 액자, 혹은 말풍선등을 추가하고 싶다고 가정한다.
  • 상속을 통해 기능을 구현하는 경우 엄밀히 말하면 객체에 기능을 추가하는 것이 아니라 Class에 기능을 추가한 것이기에 사실상 새로운 기능이 추가된 새로운 객체를 호출해야한다. 뿐만아니라 중복적인 기능의 추가시 코드가 복잡해진다.
  • 상속이 아니라 포함(이미 생성된 객체를 호출해서 활용)을 통해 기능을 추가
  • 또한 중복적으로 값을 추가하기 위해서 객체를 생성하는 클래스와, Decorator 모두 상속해야하는 공통의 부모 클래스를 추가하하여(IDraw 함수, Composite의 component와 유사한 역할) 해결.
  • 추가적으로 Operation() 함수들은 전달받은 객체의 Operation() 함수를 호출하고, 부가 적인 기능을 만을 추가
class Frame : public Image 
{
public:
	using Image::Image;

	void draw() const 
	{ 
		std::cout << "==========================" << std::endl; //부가기능
		Image::draw();
		std::cout << "==========================" << std::endl; 
	}
};
class Balloon : public Image 
{
public:
	using Image::Image;

	void draw() const 
	{ 
		std::cout << "== Balloon ==============" << std::endl; //부가기능
		Image::draw();
		std::cout << "== Balloon ==============" << std::endl; 
	}
};

다양한 종류의 객체를 전달받아 사용하고 싶은 경우, 공통의 인터페이스를 만들고 Upcasting을 활용하여 해결

0개의 댓글