본문 바로가기
  • 프론트엔드 개발자 세오세오 | Frontend dev Seo
Learn to Code

[디자인패턴] 자바스크립트로 전략 패턴(Strategy Pattern) 구현하기

by CEOSEO 2024. 6. 11.
728x90
반응형

 

1. 전략패턴(Strategy Pattern)이란?

전략 패턴(Strategy Pattern)은 객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략(알고리즘)을 객체화하여 동적으로 행위를 변경할 수 있게 해주는 디자인 패턴이다. 이 패턴은 여러 알고리즘을 하나의 추상적인 인터페이스로 묶어 알고리즘군을 정의하고, 각 알고리즘을 구체적인 전략 클래스로 캡슐화하여 필요에 따라 서로 교체 가능하게 만든다. 이를 통해 클라이언트는 알고리즘의 내부 구조를 알 필요 없이 유연하게 알고리즘을 변경할 수 있다.

 

 

알고리즘군이란?

- 동일한 기능을 수행하지만 다른 방식으로 구현된 알고리즘들의 모음

 

예)

- "정렬"이라는 동일한 문제를 해결하는 알고리즘 군 안에는 버블정렬, 삽입정렬, 퀵정렬, 병합정렬 등이 있다.

- 이 알고리즘 군에 들어있는 알고리즘들은 모두 "정렬"이라는 동일한 문제를 해결하지만, 각각의 알고리즘은 다른 방식으로 동작한다.

 

 

728x90

 

 

2. 전략 패턴의 주요 장점

1. 유연성 제공:

전략 패턴은 알고리즘을 쉽게 교체할 수 있는 유연성을 제공한다. 예를 들어, 특정 기능을 수행하는 여러 가지 방법이 있을 때, 이 패턴을 사용하면 런타임에 알고리즘을 변경할 수 있다. 이는 다양한 상황에 따라 동적으로 행위를 변경할 수 있게 해준다.

 

2. 코드 재사용성 향상:

알고리즘을 별도의 클래스나 객체로 분리하여 재사용할 수 있게 한다. 여러 클라이언트 객체가 동일한 알고리즘을 공유할 수 있으며, 코드 중복을 줄여준다. 이는 코드의 유지보수를 용이하게 한다.

 

3. 유지보수성 향상:

알고리즘을 각기 다른 클래스에 캡슐화함으로써, 특정 알고리즘의 변경이 다른 코드에 영향을 미치지 않는다. 이는 코드의 수정이 필요한 경우 변경의 범위를 최소화하여 유지보수를 쉽게 한다.

 

4. 확장성 증대:

새로운 알고리즘을 추가할 때 기존 코드를 수정할 필요 없이 새로운 전략 클래스를 추가하면 된다. 이는 시스템의 확장성을 크게 향상시킨다. 새로운 요구사항이 생길 때마다 간단히 새로운 전략을 추가할 수 있다.

 

 

 

3. 전략 패턴의 구조

전략 패턴은 다음과 같은 주요 구성 요소들로 이루어져 있다.

 

1. 컨텍스트(Context):

역할: 클라이언트가 사용할 인터페이스를 제공하며, 알고리즘을 동적으로 변경할 수 있게 해주는 클래스이다. 컨텍스트는 내부적으로 Strategy 객체를 유지하며, 이를 통해 클라이언트가 요청한 작업을 수행한다.

 

 

2. 전략 인터페이스(Strategy Interface):

역할: 알고리즘을 캡슐화하여 여러 알고리즘을 하나의 추상적인 인터페이스로 정의한다. 이를 통해 다양한 알고리즘을 동일한 방식으로 사용할 수 있게 한다.

 

 

3. 구체적인 전략 클래스들(Concrete Strategy Classes):

역할: 전략 인터페이스를 구현하여 실제 알고리즘을 제공하는 클래스들이다. 각 클래스는 특정 알고리즘을 구현하며, 컨텍스트에서 필요에 따라 이 알고리즘을 사용할 수 있다.

 

 

+--------------------+          +--------------------------+
|      Context       |          |      Strategy Interface   |
|--------------------|          |--------------------------|
| - strategy: Strategy |<>--------| + useAlgorithm(): void   |
|--------------------|          +--------------------------+
| + setStrategy(s: Strategy): void |
| + executeStrategy(): void     |
+--------------------+
          |
          | uses
          v
+-------------------------+
|   Concrete Strategy A   |
|-------------------------|
| + useAlgorithm(): void  |
+-------------------------+
          |
          | uses
          v
+-------------------------+
|   Concrete Strategy B   |
|-------------------------|
| + useAlgorithm(): void  |
+-------------------------+
          |
          | uses
          v
+-------------------------+
|   Concrete Strategy C   |
|-------------------------|
| + useAlgorithm(): void  |
+-------------------------+

 

 

 

4. 예시

전략 패턴의 예시를 Player라는 클래스와 4개의 직업 - 전사, 궁수, 마법사, 성직자-, 그리고 각각의 무기 4개 - 검, 활, 지팡이, 메이스 - 로 구현해보자. 이 예시를 위에서 말한 전략 패턴의 주요 구성 요소에 아래와 같이 대입할 수 있다.

 

1. 컨텍스트(Context):

 Player 클래스는 무기 전략을 설정하고, 이를 사용하여 공격하는 역할을 한다. Player 객체는 무기 전략을 변경할 수 있으며, attack 메서드를 호출하면 현재 설정된 전략에 따라 공격 행동을 수행한다.

역할: 클라이언트가 사용할 인터페이스를 제공하며, 무기 사용 전략을 동적으로 변경할 수 있게 해준다.

예시: Player 클래스가 컨텍스트의 역할을 한다.

 

// 플레이어 클래스

class Player {
    constructor(name, strategy) {
        this.name = name;
        this.setStrategy(strategy);
    }

    setStrategy(strategy) {
        if (!(strategy instanceof WeaponStrategy)) {
            throw new Error("전략은 WeaponStrategy의 인스턴스여야 합니다.");
        }
        this.strategy = strategy;
    }

    attack() {
        console.log(`${this.name}이(가) ${this.strategy.useWeapon()}`);
    }
}

 

 

2. 전략 인터페이스(Strategy Interface):

WeaponStrategy 클래스는 무기 사용 방법을 정의하는 추상 클래스이다. useWeapon 메서드는 각 무기 전략 클래스가 구현해야 하는 메서드이다. 이 인터페이스를 통해 Player 클래스는 구체적인 무기 사용 방법을 알 필요 없이, 무기를 사용할 수 있다.

역할: 무기 사용 방법을 캡슐화하여 여러 무기 사용 전략을 하나의 추상적인 인터페이스로 정의한다.

예시: WeaponStrategy 클래스가 전략 인터페이스의 역할을 한다.

 

// WeaponStrategy 인터페이스

class WeaponStrategy {
    useWeapon() {
        throw new Error("useWeapon 메서드를 구현해야 합니다.");
    }
}

 

 

3. 구체적인 전략 클래스들(Concrete Strategy Classes):

역할: 전략 인터페이스를 구현하여 실제 무기 사용 방법을 제공하는 클래스들이다. 각 클래스는 특정 무기 사용 방법을 구현한다.

예시: SwordStrategy, BowStrategy, StaffStrategy, MaceStrategy 클래스들이 구체적인 전략 클래스들이다.

 

// 구체적인 전략 클래스

class SwordStrategy extends WeaponStrategy {
    useWeapon() {
        return "검으로 공격합니다!";
    }
}

class BowStrategy extends WeaponStrategy {
    useWeapon() {
        return "활로 공격합니다!";
    }
}

class StaffStrategy extends WeaponStrategy {
    useWeapon() {
        return "지팡이로 공격합니다!";
    }
}

class MaceStrategy extends WeaponStrategy {
    useWeapon() {
        return "메이스로 공격합니다!";
    }
}

 

 

사용예시)

const warrior = new Player("전사", new SwordStrategy());
warrior.attack();  // 전사가 검으로 공격합니다!

const archer = new Player("궁수", new BowStrategy());
archer.attack();  // 궁수가 활로 공격합니다!

const mage = new Player("마법사", new StaffStrategy());
mage.attack();  // 마법사가 지팡이로 공격합니다!

const cleric = new Player("성직자", new MaceStrategy());
cleric.attack();  // 성직자가 메이스로 공격합니다!

 

 

 

 

728x90
반응형

댓글