반응형

스트래티지 패턴(Stragety Pattern)이란?


스트래티지 패턴(Strategy pattern)은 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다. 


스트래티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.


즉, 행위를 클래스로 캡슐화 하여 동적으로 행위를 바꾸어도 코드가 복잡해 지지 않도록 한다.


여기서의 패턴 이름과 같이 전략을 쉽게 바꾸도록 해주는 디자인 패턴이다.


ex) sorting 알고리즘 여러개가 있는데 이중 하나를 고르려고 할 때



이때, 스트래티지 패턴을 이용하면 condition statement가 현저히 줄어드는 장점이 있다.




디자인 원칙


코드에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리시킨다. 

(달라지는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 "캡술화")


상속보다는 구성을 활용한다.(상속 보다는 객체의 합성을 중요시 하자)


상속보다는 구성을 활용한다. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.





클래스 설명


Strategy


외부에서 동일한 방식으로 알고리즘을 호출 할 수 있도록 명시해둔 인터페이스


ConcreteStrategy


스트래티지 인터페이스에서 명시해둔 코드를 실제로 구현한 클래스


Context


스트래티지 패턴을 이용하는 역할을 수행하는 추상 클래스

필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 하기위해 setter 집약 관계 메서드를 제공한다.


집약 관계


- 참조값을 인자로 받아 필드를 세팅하는 경우

- 전체 객체의 라이프타임과 부분 객체의 라이프 타임은 독립적이다.

- 즉, 전체 객체가 메모리에서 사라진다 해도 부분 객체는 사라지지 않는다.



Stragety Pattern을 오리 게임을 만드는 것을 이용하여 한번 생각해보자.


https://jusungpark.tistory.com/7




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package StrategyPattern;
 
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public void swim(){
        System.out.println("물에 떠있습니다.");
    }
 
    public abstract void display();
    
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
 
    public void getFlyBehavior(){
        flyBehavior.fly();
    }
 
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
 
    public void getQuackBehavior(){
        quackBehavior.quack();
    }
 }
cs


Duck 추상 클래스를 만들어준다.


여기서는 이제 set, get을 통해서 fly와 quack에 관한 값만 받아 올 수 있도록 한다.


1
2
3
4
5
package StrategyPattern;
 
public interface FlyBehavior {
    public void fly();
}
cs


FlyBehavior 인터페이스를 만들고 fly 메서드를 정의해준다.


1
2
3
4
5
6
7
8
9
package StrategyPattern;
 
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("날고 있습니다.");
    }
}
 
cs


1
2
3
4
5
6
7
8
9
package StrategyPattern;
 
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("날지 못하고 있습니다.");
    }
}
 
cs


각각 행동에 대한 인터페이스를 구현해준다.

지금은 난다, 날수 없다 두개의 행동을 구현했다.


1
2
3
4
5
6
package StrategyPattern;
 
public interface QuackBehavior {
    public void quack();
}
 
cs


1
2
3
4
5
6
7
8
9
package StrategyPattern;
 
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("꽥꽥");
    }
}
 
cs


1
2
3
4
5
6
7
8
9
package StrategyPattern;
 
public class NoQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("소리를 못냅니다.");
    }
}
 
cs


마찬가지로 QuackBehavior 인터페이스를 만들고 그에 해당하는 행동을 만들어준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
package StrategyPattern;
 
public class MallardDuck extends Duck{
    public MallardDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
    
    @Override
    public void display() {
        System.out.println("청둥오리 입니다.");
    }
}
 
cs


실제 오리가 될 클래스를 만들어주고, 생성자로 오리 클래스에 fly,quack에 대해 객체를 생성해준다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package StrategyPattern;
 
public class DuckGame {
 
    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
 
        mallard.getQuackBehavior();
        mallard.getFlyBehavior();
        
        System.out.println();
        
        mallard.setFlyBehavior(new FlyNoWay());
        mallard.getQuackBehavior();
        mallard.getFlyBehavior();
        
        System.out.println();
        
        mallard.setQuackBehavior(new NoQuack());
        mallard.getQuackBehavior();
        mallard.getFlyBehavior();
    }
 
}
 
cs


마지막으로 실제 오리 게임에서


오리 객체를 생성해주면 오리는 fly, quack에 대해 기본 상태를 가지게 되고


지금부터는 코드의 복잡함 없이 각 클래스에서 필요한 메서드만 호출하면 되고


FlyBehavior, QuackBehavior쪽에서는 그에 맞는 행동만 정의하고 구현해주면 된다.

반응형