[Design Pattern] Strategy Pattern

younghyun·2022년 10월 25일
0

Design Pattern

목록 보기
3/14
post-thumbnail

Strategy Pattern 이란

실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴으로, 특정한 계열의 알고리즘들을 정의하고, 각 알고리즘을 캡슐화하며, 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다.

1) 객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성
2) 유사한 행위들을 캡슐화 하는 인터페이스를 정의
3) 객체의 행위를 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함

설계

  • Strategy (인터페이스 or 추상 클래스)
    : 외부에서 동일한 방식으로 알고리즘을 호출하는 방법을 명시
    • 인터페이스 사용: 속성 필요 없을 때
    • 추상 클래스 사용: 변수나 속성이 필요할 때
  • ConcreteStrategy (구현 클래스)
    : Strategy 패턴에서 명시한 알고리즘을 실제로 구현한 클래스
  • Context
    • Strategy 패턴을 이용하는 역할을 수행한다.
    • 필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 setter메서드를 제공한다.

예시

오리의 행동 분석을 해보자.

  • MallardDuck(청둥오리): fly, quack, swim, display
  • RubberDuck(장난감오리): quack, swim, display
  • DecoyDuck(나무오리): swim, display

⭐디자인원칙 1. 바뀌는 부분을 바뀌지 않는 부분으로부터 분리시킨다.

swimdisplay는 일정하고, flyquack이 바뀐다.

각각의 행동을 구현한 클래스를 Duck 클래스로부터 독립적으로 만들어서 구현해보자.
fly행동을 구현한 인터페이스 FlyBehavior, quack행동을 구현한 인터페이스 QuackBehavior

Duck과 Behavior의 완벽한 분리를 이루어내자.
다른 Behavior 혹은 새로운 Duck 클래스 생성 가능 "확장이 쉬움"

⭐디자인원칙 2. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.

각 행동의 큰 틀은 인터페이스 FlyBehavior, QuackBehavior로 표현하고, 구체적인 설명은 각 인터페이스를 상속받아 구현한다.

⭐디자인원칙 3. 상속보다는 구성을 활용한다.

오리클래스들은 특정 행동을 상속받는 것이 아닌, 특정 행동객체(FlyBehaviorQuackBehavior)로 구성됨으로써 행동이 부여된다.

Strategy (Interface, 오리마다 바뀌는 행동 골라서 만듦)

public interface FlyBehavior{
    void fly();
}
public interface QuackBehavior{
    void quack();
}

ConcreteStrategy (Strategy에서 명시한 각각의 행동을 구현한 클래스)

public class Quack implements QuackBehavior{
    @Override
    public void quack(){
        System.out.println("quack");
    }
}
public class MuteQuack implements QuackBehavior{
    @Override
    public void quack(){
    }
}
public class Squeak implements QuackBehavior{
    @Override
    public void quack(){
        System.out.println("squeak");
    }
}
public class FlyNoWay implements FlyBehavior{
    @Override
    public void fly(){
    }
}
public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly(){
        System.out.println("fly with wings");
    }
}

Context (Strategy 패턴과 setter메서드를 활용하여 오리의 행동 명시)

public class Duck{
    private FlyBehavior flyBehavior;
    private QuackBehavior quackBehavior;
    
    public void swim(){
        System.out.println("swim");
    }
    
    public void display(){
        System.out.println("Duck");
    }
    
    public void performQuack(){         // Strategy 패턴 이용 (interface에서 호출)
        if (quackBehavior != null){
            quackBehavior.quack();
        }
    }
    
    public void performFly(){          // Strategy 패턴 이용 (interface에서 호출)
        if (flyBehavior != null){
            flyBehavior.fly();
        }
    }
    
    public void setQuackBehavior(QuackBehavior quackBehavior){   // QuackBehavior 지정 함수
        this.quackBehavior = quackBehavior;
    }
    
    public void setFlyBehavior(FlyBehavior flyBehavior){       // FlyBehavior 지정 함수
        this.flyBehavior = flyBehavior;
    }
}
public class MallardDuck extends Duck{
    public MallardDuck(){
        setQuackBehavior(new Quack());        // QuackBehavior를 Quack으로 지정
        setFlyBehavior(new FlyWithWings());    // FlyBehavior를 FlyWithWings로 지정
    }
    @Override
    public void display(){
        System.out.println("Mallard Duck");
    }
}
public class RuberDuck extends Duck{
    public RubberDuck(){
        setQuackBehavior(new Squeak());
        setFlyBehavior(new FlyNoWay());
    }
    
    @Override
    public void display(){
        System.out.println("Rubber Duck");
    }
}
public class DecoyDuck extends Duck{
    public DecoyDuck(){
        setQuackBehavior(new MuteQuack());
        setFlyBehavior(new FlyNoWay());
    }
    
    @Override
    public void display(){
        System.out.println("Decoy Duck");
    }
}

Main

public class Main{
    public static void main(Strings[] args){
        Duck duck1 = new MallardDuck();
        duck1.display();
        duck1.performQuack();
        duck1.performFly();
        
        Duck duck2 = new RubberDuck();
        duck2.display();
        duck2.performQuack();
        duck2.performFly();
        
        Duck duck3 = new DecoyDuck();
        duck3.display();
        duck3.performQuack();
        duck3.performFly();
    }
}


// 결과
Mallard Duck
quack
fly with wings
Rubber Duck
squeak
Decoy Duck
profile
🌱 주니어 백엔드 개발자입니당

0개의 댓글