Strategy Pattern. 디자인 패턴

전략 패턴은 객체지향 프로그래밍에서 아주 기초가 되고 중요한 패턴입니다. 객체지향 프로그래밍의 핵심인 다형성을 이용한, 아니 이 패턴이 다형성일 정도로 중요 합니다. 

전략 패턴의 예제는 일상생활에서 매일 벌어 집니다. 집에서 회사로 출근을 합니다. '집에서 회사로 출근하다' 라는 말에는 방법이 없습니다. 단지 '출근하다' 라는 동작이 있을뿐 어떤 수단, 버스나 걷는거 혹은 자전거를 타는거, 등 아주 많습니다. 또, 농구 경기에서 선수들은 슛을 합니다. 그런데 슛에는 3점슛, 2점슛, 자유투등 방법은 가지가지 입니다. 

전략 패턴이 바로 이러한 것입니다. 어떤 행위의 목적은 모두 동일 하지만 그 방법이 모두 다를때에 이 방법을 객체화함으로써 객체의 확장성을 높여줍니다. 일단 전략 패턴을 설명하기 전에 농구 예제를 한번 구현해보겠습니다.


class BasketShooting
{
public function shooting($mark)
{
$res = '';
switch($mark)
{
case '2':
$res = '2점슛';
break;
case '3':
$res = '3점슛';
break;
default:
$res = '자유투';
break;
}

return $res;
}
}


슛을 하는 메소드를 만들고 거기에 Switch 문으로 그냥 간단하게 값을 리턴하도록 구현했습니다. 여기서 중요한 것을 상기해야 하는것은 이 슛예제에서 처리하는 Switch 은 아주 단순하게만 한것입니다. 만일 복잡한 로직을 채워넣는다고 상상을 해봅시다. 예를들면 각 슛에 대해서 예외처리를 해준다거나 뭔가를 더 처리를 해줘야 할 경우에 Switch 문을 잘 알아야 합니다. Switch 문을 알아야 한다지만 저 클래스 안에 메소드가 많이 있을 경우에 shooting 이라는 메소드를 찾아야 하고 그 않에 로직을 다시 체크해야 합니다. 

더 큰 문제는 외부 객체에서 이것을 사용해야 할 경우에는 문제가 될수 있습니다. 2점슛만 필요할 경우가 있을 수 있습니다. 그런데도 모든 로직을 다 가지고 가야 하고 이는 2점슛만을 필요로하는 객체에서는 모든 슛을 알수 있게 됩니다. 

이럴때에 다형성을 이용하면, 즉 전략 패턴을 이용하면 슛을 하는 행위와 그 행위의 방법을 분리하고 행위자체를 은닉할 수 있습니다. 전략 패턴은 목적은 같은데 방법을 객체로 분리하고싶을때 사용하는데, 여기서 목적은 모두 동일하기 때문에 이를 규격, 프로토콜로 모두 동일하게 해야하는데 이때 인터페이스를 사용합니다. 여기서는 슛이라는 것을 인터페이스화 합니다.

interface IShooting
{
public function shoot();
}

슛을 하는 방법을 객체화하기 위해서 클래스를 만듭니다. 여기서 인터페이스를 구현하는 클래스라는 점을 명심하십시오.


class Point2Shooting implements IShooting
{
public function shoot()
{
return '2점슛';
}
}


class Point3Shooting implements IShooting
{
public function shoot()
{
return '3점슛';
}
}


class PointFreeShooting implements IShooting
{
public function shoot()
{
return '자유투';
}
}


위의 클래스들은 전부 shoot 이라는 행위에 대한 클래스들입니다. IShooting 이라는 인터페이스를 사용해서 슛이라는 목적을 모두 구현한 것입니다. 이것을 다음과 같이 슛을 사용할 행위자를 만듭니다.

class BaseketBallPlayer
{
public function shoot(IShooting $shooting)
{
return $shooting->shoot();
}
}



실제 사용은 다음과 같이 합니다.

require_once '/Users/histlist/Sites/StrategyPattern/BasketBallPlayer.php';
require_once '/Users/histlist/Sites/StrategyPattern/IShooting.php';
require_once '/Users/histlist/Sites/StrategyPattern/Point2Shooting.php';
require_once '/Users/histlist/Sites/StrategyPattern/Point3Shooting.php';
require_once '/Users/histlist/Sites/StrategyPattern/PointFreeShoot.php';

class BasketBallPlayerTest extends PHPUnit_Framework_TestCase
{

public function testShooting()
{
$obj = new BasketBallPlayer();
$this->assertInstanceof('BasketBallPlayer', $obj);
$this->assertEquals('2점슛', $obj->shoot(new Point2Shooting()));
$this->assertEquals('3점슛', $obj->shoot(new Point3Shooting()));
}
}

플레이어 객체에 슛의 방법을 넘겨준다는 것에 주목하십시오. 만일 슛의 방법을 바꾸고자 한다면 객체를 넘겨주면 됩니다. 슛의 방법을 추가하고자 한다면 새로운 클래스를 만들고 객체를 생성해서 넘겨주면 됩니다. 이러한 슛의 방법은 플레이어 말고도 어디서든지 필요하면 가져다 쓸수 있습니다. 객체지향 프로그래밍의 재사용성을 높여줍니다.

전략패턴은 객체지향 프로그래밍에서 매우 중요하고 기본이 되는 패턴입니다.









덧글

댓글 입력 영역