알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만들다.
스트레티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.
오리 시뮬레이션
duck의 행동들 중 swin()의 경우 모든 duck이 똑같이 행동한다고 가정하자
quack()과 fly()의 경우 duck마다 행동이 달라질수 있다고 가정하자
-> display()는 추상메소드
바뀌는 부분
1. quack()
2. fly()
바뀌지 않는 부분
1. swim()
바뀐다고 예상한 quack()과 fly()를 알고리즘군으로 각각 묶은 새로운 클래스 집합을 생성한다.
Duck 클래스에 FlyBehavior, QuackBehavior 형식의 필드를 생성한다.
캡슐화된 행동들이 Duck에 필드로 구성
되어있다.
strategy 패턴에 사용된 디자인 원칙
- 바뀌지않는 부분과 바뀌는 부분을 분리하고 바뀌는 부분을 캡슐화 한다.
- 상속보다는 구성을 활용한다.
- 구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.(구성활용)
strategy 패턴으로 얻은 점
- 서브클래스가 모든 행동을 똑같이 구현하지 않아도 된다.
- 같은 행동을 하는 서브클래스끼리는 코드를 재사용할 수 있다.
- 코드 실행시에도 인터페이스를 이용해 다른 행동을 하도록 만들수도 있다.
- 서브클래스들은 행동을 직접 처리하는 대신 다른 객체에 그 행동을 위임한다.
- Duck과 그 서브클래스들과 행동이 분리되어 있기에 다른 클래스에서도 알고리즘군을 재사용할 수 있다.
Duck 슈퍼클래스
public abstract class Duck
{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck()
{
}
public void swim()
{
Console.WriteLine("오리 수영");
}
public void performFly()
{
flyBehavior.fly();
}
public void performQuack()
{
quackBehavior.quack();
}
public abstract void display();
}
}
서브클래스 Duck
class MallardDuck : Duck
{
public MallardDuck()
{
flyBehavior = new FlyWithWing();
}
public override void display()
{
Console.WriteLine("나는 mallard오리얌");
}
}
FlyBehavior 알고리즘군
public interface FlyBehavior
{
public void fly();
}
public class FlyWithWing : FlyBehavior
{
public void fly()
{
Console.WriteLine("나는 날개로 난다");
}
}
public class FlyNoWay : FlyBehavior
{
public void fly()
{
Console.WriteLine("나는 못날어");
}
}
테스트
class Program
{
static void Main(string[] args)
{
Duck someDuck1 = new MallardDuck();
someDuck1.display();
someDuck1.performFly();
}
}
결과
나는 mallard오리얌
나는 날개로 난다