본문으로 바로가기

스트래티지 패턴 (Strategy Pattern)

category 디자인패턴 2022. 3. 29. 17:51

스트래티지 패턴: 여러 알고리즘을 하나의 인터페이스를 통해 만들고 각각 캡슐화 하여 교체할 수 있도록 만든 패턴 

 

 

 

예시) 

게임을 하나 구현한다고 예시를 든다. 

 

객체지향으로 프로그래밍하여, 

 

게임에는 유저가 사용할 수 있는 무기가 있으며

초기 종류는 검, 칼, 지팡이 가 있다.

 

각 무기는 공격하는 attack() 을 가지고 있고 display() 기능을 보유하고 있다. 

 

 

public abstract class Weapon {
    public void attack() {
        System.out.println("휘두른다");
    }
    abstract void display();
}




public class Sword extends Weapon{
    @Override
    void display() {
        System.out.println("검");
    }
}

public class Knife extends Weapon{
    @Override
    void display() {
        System.out.println("칼");
    }
}

public class Wand extends Weapon{
    @Override
    void display() {
        System.out.println("지팡이");
    }
}

 

 

 

그런데 나중에 wand에 마법을 사용할 수 있는 기능이 추가되었다면 ?

public abstract class Weapon {
    public void attack() {
        System.out.println("휘두른다");
    }
    
    public void spell() {
        System.out.println("마법을 사용한다");
    }
    
    abstract void display();
}


public class Sword extends Weapon{
    @Override
    void display() {
        System.out.println("검");
    }
    
    @Override
    public void spell() {
        //
    }
}


public class Knife extends Weapon{
    @Override
    void display() {
        System.out.println("칼");
    }
    
    @Override
    public void spell() {
        //
    }
}

 

상속인한 문제로 Knife와 Sword가 마법을 사용하는 오류가 나타나게 된다. 

임시 방편으로 spell을 오버라이드 하여 아무것도 작동하지 않도록 만들었다. 

 

아무것도 작동하지 않는 코드를 만들고 , 

이후에 spell에 대한 요구사항이 세분화 되어 불을 만드는 주문, 물을 만드는 주문.. 등으로 세분화 된다면

 

그때마다 각 클래스에 재정의 해야 하고 작은 로직이라도 바뀔 경우 모든 class 에서 코드를 재작성 해야하는 대참사가 일어날 수 있다. 

 

디자인 패턴에서, 코드는 수정에 대해 폐쇄적이고 확장할 수 있도록 구성되어야 한다. 

 

 

무기라는 객체에 대해 행위를 인터페이스로 나타내어 유연하게 동작할 수 있도록 변경한다. 

 

public abstract class Weapon {
    Spell spell;
    
    public void attack() {
        System.out.println("휘두른다");
    }
    
    public void spell() {
        this.spell.spell();
    }
    
    public void setSpell(Spell spell) {
        this.spell = spell;
    }
    
    abstract void display();
}



public interface Spell {
    void spell();
}

public class SpellWithFire implements Spell{
    @Override
    public void spell() {
        System.out.println("Fire spell");
    }
}

public class SpellWithWater implements Spell{
    @Override
    public void spell() {
        System.out.println("Water Spell");
    }
}

public class SpellWithNothing implements Spell{
    @Override
    public void spell() {
        System.out.println("Nothing");
    }
}

 

Spell 이라는 행위를 인터페이스화 하여 세분화 된 주문은 implement를 통해 구현한다. 

 

이렇게 알고리즘을 분리하고 인터페이스를 통해 접근하게 된다면 후에 특정 알고리즘이 변경, 추가 되어도 모든 class에서 접근할 필요가 없고 해당 구현체만 수정하면 된다. 

 

 

 

'디자인패턴' 카테고리의 다른 글

[디자인패턴] 템플릿 메소드 패턴  (0) 2023.01.02
싱글톤 패턴 (Singleton)  (0) 2022.05.19
객체 지향 설계 SOLID 5원칙  (0) 2022.04.08