Strategy Pattern
클래스별로 캡슐화되어 있는 객체들을 교체할 수 있도록 함으로써 같은 작업을 다른 알고리즘으로 사용할 수 있도록 하는 패턴
- Strategy 클래스 내 각각 캡슐화 그리고 구성을 통해 알고리즘 바꿀 수 있다.
- Strategy Pattern 은 클라이언트가 독립적으로 다양한 알고리즘을 사용한다.
- 다형성을 이용하여 특정 객체에 종속되지 않도록 한다. 다른 부분을 분리하여 캡슐화한다.
상속하지 않는 대신 인터페이스를 통해 캡슐화(추상화)한다. (상속 대신 구성 사용)
분리된 strategies 인터페이스에서 behaviors(행동)이 정의된다.
behavior 과 behavior을 사용하는 class 사이에는 더 나은 decoupling 이다.
Behaviors 는 런타임시에도 변경할 수 있다.
* 캡슐화 : 구조적 설계에서 모듈화와 같은 의미로 객체를 정의할 때 연관된 속성과 방법을 한 테두리로 묶는 것
* 다형성 : 상속받은 여러 개의 하위 객체들이 다른 형태의 특성을 갖는 객체로 이용될 수 있는 성질
Strategy Pattern 은 코드상 어떤 문제점이 있을 때 활용할 수 있을까?
상속을 통해 행동을 확장하고
슈퍼 클래스에 새로운 행동을 추가했다.
슈퍼 클래스에 추가된 fly()는
모든 subclass 에게 적용되고 영향을 준다.
문제점)
- 각 subclass 에서 원하지 않는 결과가 발생하는 지 검사
ex) 고무오리는 날지 못함
- 슈퍼클래스에 추가된 fly() 는 모든 subclass 에게 적용된다.
문제 해결)
Duck 클래스 에서 fly()를 분리하고 캡슐화 한다.
클래스(애플리케이션)에서
변경 가능한 부분을 분리하고 추상화 / 캡슐화 한다.
-->> OCP : 닫힘은 추상화에 기반, 변경 가능성 있는 부분을 추상화한다.
※ (abstract) class vs interface
(설계원칙) interface에 맞춰 프로그래밍
구현에서 실제 변수 ,메소드 변경에 영향을 받을 수 있다.
공유되는 코드가 많을 때 추상클래스
(설계원칙) 상속 inheritance 보다 구성 composition.
분리한 코드에 구성을 사용하여 통합한다.
Polymorphic Composition 을 통한 클래스의 행동 확장
- 클래스에서 변경 가능한 부분을 분리하고 추상화
- 분리한 부분을 구성을 사용하여 통합
Polymorphic Composition) interface 구성
Composition of Abstraction(interface) (not Concretion) / 구현X -> 변경영향 적음
Strategy or Policy : 행동을 추상화한 클래스
interface > 추상(abstract) > 구상(concrete)
추상화
// Strategy: fly() 행동 추상화
public interface FlyBehavior {
public void fly();
}
행동 구현
// Mechanisms: Strategy를 구현함
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
Polymorphic Composition
// swim, fly, setFlyBehavior은 동일
public abstract class Duck // Context
{
FlyBehavior flyBehavior; // Polymorphic Composition
abstract void display();
public void swim() { System.out.println("All ducks float, even decoys!"); }
public void fly() { flyBehavior.fly(); } // Delegation
// 실행 중 행동 변경도 가능
public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; }
}
subclass 들이
공유하는 코드는 abstract에서 구현
public void swim() { System.out.println("All ducks float, even decoys!"); }
public void fly() { flyBehavior.fly(); } // Delegation
// 실행 중 행동 변경도 가능
public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; }
public class MallardDuck extends Duck
{
// 생성자에서 자신의 (default) 행동 생성(설정)
public MallardDuck() { flyBehavior = new FlyWithWings(); }
public void display() { System.out.println("I'm a real Mallard duck"); }
}
메인 실행
// client
public class MiniDuckSimulator1
{
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.fly();
Duck rubber = new RubberDuck();
rubber.fly();
// client가 실행 중 context의 행위 변경 (행동 변경의 유연성↑)
// 런타임때 행동을 바꿀수 있다.
rubber.setFlyBehavior(new FlyRocketPowered());
rubber.fly();
}
}
다이어그램
인터페이스 (What to do)
추상클래스 : 공유 연산이 많을 때
concreate 클래스(How to do)
댓글