컴퓨터과학/0 + 소프트웨어 아키텍처(디자인 패턴)

[소프트웨어 아키텍처] 2. 전략 패턴(Strategy Pattern -java)

힘들면힘을내는쿼카 2022. 10. 25. 08:46
728x90
반응형

 

전략패턴

알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 사용 할 수 있게하는 패턴 입니다.
클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있다.

 

 

하나의 움짤에 여러가지 전략을 설정할 수 있습니다.

변하지 않는 것은 움짤,

변하는 것은 전략 입니다.

 

상속이 모든 문제를 해결할 수는 없습니다.(템플릿 메소드 패턴에서는 상속을 사용합니다.)

2022.10.25 - [컴퓨터 공학/0 + 소프트웨어 아키텍처] - [소프트웨어 아키텍처] 5. 템플릿 메소드 패턴(Template method Pattern -java)

 

[소프트웨어 아키텍처] 5. 템플릿 메소드 패턴(Template method Pattern -java)

템플릿 메소드 패턴 커멘드 패턴에서 우리는 메서드의 호출을 캡슐화 했습니다. 이번에는 서브클래스에서 언제든 필요할 때마다 알고리즘을 가져다가 사용 할 수 있도록 캡슐화 해보겠습니다.

howisitgo1ng.tistory.com

(템플릿 메소드 패턴은 상속을 이용하여 변하는 부분은 자식이 처리하기 때문에, 자식클래스는 사용하지 않는 부모클래스의 기능을 상속 받습니다.)


서브클래스마다 객체의 행동(알고리즘)이 바뀔수 있는데 모든 서브클래스에서 한 가지 행동(알고리즘)만 사용하도록 하는 것은 올바르지 못하기 때문입니다.


그래서 행위1(알고리즘1), 행위2(알고리즘2) 인터페이스를 만들어서 서브 클래스에 상속하는 방법은 어떤가요?
이렇게 되면, 행위1을 사용하는 특정 서브클래스들의 행위가 변경 될때 마다 찾아서 전부 수정해야 합니다.🙀
그 과정속에서 버그도 생길 가능성이 있죠..! 😭

캡슐화

바뀌는 부분은 따로 뽑아서 캡슐화(Strategy) 한다.
그러면 나중에 바뀌지 않는 부분(Contexct)에는 영향을 미치지 않고 그 부분만 고치거나 확장할 수 있다.

 

위 개념은 매우 간단하지만 다른 모든 디자인 패턴의 기반을 이루는 원칙입니다.

달라지는 부분을 찾아서
나머지 코드에 영향을 주지 않도록 캡슐화 합니다.

그러면 코드를 변경하는 과정에서
의도치 않게 발생하는 일을 줄이면서
시스템의 유연성을 향상시킬 수 있습니다.

전략 패턴의 구조

  • Context
    • 전략 패턴을 이용하는 역할 수행
    • 구성(composition)을 이용하기 때문에 setStrategy()를 이용하여 전략을 유연하게 변경한다.
  • Strategy
    • 전략(알고리즘)을 호출하는 방법 명시
  • ConcreteStrategy1, ConcreteStrategy2
    • 전략(알고리즘)을 구현하는 역할 수행

 

삼국지 장수별 공격 방법 구현

유비, 관우를 등록하고 전략 패턴을 사용하여 무기별로 공격 방법을 구현해 봅시다.

AttackBehavior

public interface AttackBehavior {
    void attack();
}

AttackKnife

public class AttackKnife implements AttackBehavior {
    @Override
    public void attack() {
        System.out.println("칼로 공격!");
    }
}

AttackSpear

public class AttackSpear implements AttackBehavior {
    @Override
    public void attack() {
        System.out.println("창으로 공격");
    }
}

Solider

abstract public class Soldier {
    AttackBehavior attackBehavior;
    public void attack() {
        attackBehavior.attack();
    }
    public void setAttackBehavior(AttackBehavior attackBehavior) {
        this.attackBehavior = attackBehavior;
        System.out.println("공격 방법 변경!");
    }
    abstract void display();

}

GuanYu

public class GuanYu extends Soldier {

    public GuanYu() {
        attackBehavior = new AttackSpear();
    }

    @Override
    void display() {
        System.out.println("저는 관우 입니다.");
    }
}

YuBi

public class YuBi extends Soldier {

    public YuBi() {
        attackBehavior = new AttackKnife();
    }

    @Override
    void display() {
        System.out.println("저는 유비입니다.");
    }
}

Client

public class Client {
    public static void main(String[] args) {
        Soldier soldier1 = new GuanYu();
        Soldier soldier2 = new YuBi();

        soldier1.display();
        soldier1.attack();
        soldier1.setAttackBehavior(new AttackKnife()); // 전략 변경
        soldier1.attack();

        System.out.println("//========================//");

        soldier2.display();
        soldier2.attack();
        soldier2.setAttackBehavior(new AttackSpear()); //전략 변경
        soldier2.attack();
    }
}

결과

저는 관우 입니다.
창으로 공격
공격 방법 변경!
칼로 공격!
//========================//
저는 유비입니다.
칼로 공격!
공격 방법 변경!
창으로 공격

정리

  • 바뀌는 부분을 캡슐화 한다.
  • 상속보다는 구성을 활용한다.
  • 구현보다는 인터페이스에 맞춰서 프로그래밍 한다.
  • 전략 패턴은 알고리즘군을 정의하고 캠슐화해서 각각의 알고리즘군을 수정해서 사용할 수 있게 해준다.
  • 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.

 

 

 

 

728x90
반응형