본문 바로가기
프로그래밍/디자인패턴

스트레티지(strategy) 패턴

by 리뷰하는 (게임)프로그래머_리프TV 2010. 4. 3.



기본적인 구조는 최상위 클래스를 상속받아 그 클래스들에 기능을 추가한다. 라고 보는게 맞을듯.

어떤 상황에 좋은가?

 서로 행위만 다를 뿐 밀접한 연관 관계를 가지는 여러 클래스들에 대해 필요한 시점에 어느 한 행위를 수행하는 클래스를 골라 사용하고자 할 때 유용하다.

 저장 공간 사용 효율이나 실행 시간 효율 등의 측면에서 다양한 형태의 알고리즘(기능)이 존재해서 상황에 따라 최적의 알고리즘(기능)을 선택해서 사용하도록 할 때 유용하다.

 어떤 알고리즘(기능)이 Client가 알아서는 안될 데이터를 사용하거나 알고리즘(기능)에 종속된 복잡한 자료구조(속성)를  사용할 때 유용하다. 이 경우 Strategy 패턴은 Client에게 알고리즘(기능)이 사용하는 데이터나 자료구조(속성)를 숨겨주는 역활을 한다.

 어떤 클래스가 많은 행위를 가지고 있고 이것이 여러 개의 조건문 형태로 쭉 나열되는 형태일 때 많은 조건문 대신 Strategy 패턴을 사용하면 유용하다. 이때 각 조건에 따라 수행할 때용들은 Strategey의 하위 클래스로 정의 될 것이다.

예제의 기능은, 최상위 오리 클래스를 상속 받아,
다양한 오리들을 생성하고, 사용한다.



Duck.h

#ifndef __DUCK_H__
#define __DUCK_H__

#include "FlyBehavior.h"
#include "QuackBehavior.h"

/* 오리 클래스 */

class Duck
{
	FlyBehavior* flyBehavior;
	QuackBehavior* quackBehavior;
public:
	~Duck();
	void swim();
	virtual void display() = 0;
	void performFly();
	void performQuack();
	void SetFlyBehavior(FlyBehavior* f);
	void SetQuackBehacior(QuackBehavior* q);
};

#endif​


Duck.Cpp

#include <iostream>
#include "Duck.h"

void Duck::swim()
{
	std::cout << "수영중" << std::endl;
}
void Duck::performFly()
{
	flyBehavior->fly();
}
void Duck::performQuack()
{
	quackBehavior->quack();
}
void Duck::SetFlyBehavior(FlyBehavior* f)
{
	flyBehavior = f;
}
void Duck::SetQuackBehacior(QuackBehavior* q)
{
	quackBehavior = q;
}

Duck::~Duck()
{
	delete flyBehavior;
	delete quackBehavior;
}​


FlyBehavior.h

#ifndef __FLYBEHAVIOR_H__
#define __FLYBEHAVIOR_H__

// 하늘을 나는 기능
/* FlayBehavior Class */
class FlyBehavior
{
public:
	virtual void fly() = 0;
};

/* FlyWithWings : public FlyBehavior */
class FlyWithWings : public FlyBehavior
{
public:
	void fly();
};

/* FlyNoWay : public FlyBehavior */
class FlyNoWay : public FlyBehavior
{
public:
	void fly();
};

class FlyRoket : public FlyBehavior
{
public:
	void fly();
};

#endif​


FlyBehavior.cpp

#include <iostream>
#include "FlyBehavior.h"

void FlyWithWings::fly()
{
	std::cout << "오리가 난다." << std::endl;
}

void FlyNoWay::fly()
{
	std::cout << "오리가 못 난다." << std::endl;
}

void FlyRoket::fly()
{
	std::cout << "오리가 로켓으로 난다." << std::endl;
}​


QuackBehavior.h


QuackBehavior.h

#include <iostream>
#include "QuackBehavior.h"

void Quack::quack()
{
	std::cout << "오리가 꽥꽥" << std::endl;
}

void Squack::quack()
{
	std::cout << "오리가 삑삑" << std::endl;
}

void MuteQuack::quack()
{
	std::cout << "오리가 조용" << std::endl;
}

void CallQuack::quack()
{
	std::cout << "사냥꾼이 호출버튼을 눌러 오리 소리를 냅니다." << std::endl;
}​


main.cpp

#include <iostream>
#include "FlyBehavior.h"
#include "Duck.h"
#include "QuackBehavior.h"

class DecoyDuck : public Duck
{
public:
	void display()
	{
		std::cout << "가짜 오리 출력 " << std::endl;
	}
};

class MallardDuck : public Duck
{
public:
	void display()
	{
		std::cout << "청둥 오리 출력" << std::endl;
	}
};

class RedheadDuck : public Duck
{
public:
	void display()
	{
		std::cout << "빨간 머리 오리 출력" << std::endl;
	}
};

void main()
{
	// 가짜 오리
	DecoyDuck decoyduck;
	// 청둥 오리
	MallardDuck mallarduck;
	// 빨간 머리 오리
	RedheadDuck redheadduck;
	// 호출기 생성
	CallQuack callquack;

	// 가짜 오리의 능력들 삽입
	decoyduck.SetFlyBehavior(new FlyRoket);
	decoyduck.SetQuackBehacior(new Squack);
	// 청둥 오리의 능력들 삽입
	mallarduck.SetFlyBehavior(new FlyWithWings);
	mallarduck.SetQuackBehacior(new Quack);
	// 빨간 머리 오리의 능력들 삽입
	redheadduck.SetFlyBehavior(new FlyWithWings);
	redheadduck.SetQuackBehacior(new Quack);

	// 가짜 오리 사용
	decoyduck.display();
	decoyduck.performQuack();
	decoyduck.performFly();
	decoyduck.swim();

	std::cout << std::endl;

	// 청둥 오리 사용
	mallarduck.display();
	mallarduck.performQuack();
	mallarduck.performFly();

	std::cout << std::endl;

	// 빨간 머리 오리 사용
	redheadduck.display();
	redheadduck.performQuack();
	redheadduck.performFly();
	redheadduck.swim();

	std::cout << std::endl;

	// 호출기 사용
	callquack.quack();
}​