Posts [Design Patterns] Strategy Pattern
Post
Cancel

[Design Patterns] Strategy Pattern


Contents



스트래티지 패턴(Strategy Pattern)

알고리즘군을 정의하고 각각을 캡슐화하여 교환 가능하도록 만들어준다.

코드에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리시킨다.

바뀌는 부분을 따로 뽑아서 캡슐화시키자.
그러면 나중에 바뀌지 않는 부분에 영향을 미치지 않는채로 해당 부분만 수정하거나 확장할 수 있다.

구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.

이는 상위 형식에 맞춰서 프로그래밍한다는 의미이다.
파이썬에는 따로 인터페이스가 존재하지 않고, 모두 추상 클래스로 표현한다.

예를 들어보자.

Animal이라는 추상 클래스가 있고, Dog, Cat이라는 구상 클래스가 있을 때 다음과 같이 구성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from abc import *

class Animal(metaclass=ABCMeta):
    @abstractmethod
    def makeSound(self):
        pass

class Dog(Animal):
    def makeSound(self):
        self.bark()
    def bark(self):
        print('멍멍')

class Cat(Animal):
    def makeSound(self):
        self.meow()
    def meow(self):
        print('야옹')

dog = Dog()
dog.makeSound()

cat = Cat()
cat.makeSound()

상위 인터페이스 형식에 맞추어 구현한다면 코드는 훨씬 보기 좋아진다.
또한 makeSound라는 기능 자체는 변하지 않고, 각 클래스 별로 세분화하여 코드를 구성할 수 있다.

이런식으로 디자인한다면, 재사용이 용이해진다.
또한 기존의 코드를 건드리지 않고, 새로운 행동을 추가할 수 있다.

상속보다는 구성을 활용한다.

A는 B이다. 보다 A에는 B가 있다가 나을 수 있다.
A에는 B가 있다.를 구성을 이용하는 것이라고 부른다.
구성을 이용하여 시스템을 만들면 유연성을 크게 향상시킬 수 있다.

게임에서 다양한 캐릭터들이 있고, 사용할 무기들이 존재한다.
한 캐릭터는 한 번에 한 가지 무기를 사용할 수 있고, 무기는 교체할 수 있다.
이를 위에서 배운 방법들을 사용하면 다음과 같이 짤 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class Character(metaclass = ABCMeta):
    def __init__(self):
        self.weaponBehavior = None
    @abstractmethod
    def fight(self):
        pass
    def setWeapon(self, weaponBehavior):
        self.weaponBehavior = weaponBehavior

class Queen(Character):
    def __init__(self):
        self.weaponBehavior = SwordBehavior()
    def fight(self):
        self.weaponBehavior.useWeapon()

class King(Character):
    def __init__(self):
        self.weaponBehavior = SwordBehavior()
    def fight(self):
        self.weaponBehavior.useWeapon()

class Troll(Character):
    def __init__(self):
        self.weaponBehavior = AxeBehavior()
    def fight(self):
        self.weaponBehavior.useWeapon()

class Knight(Character):
    def __init__(self):
        self.weaponBehavior = KniftBehavior()
    def fight(self):
        self.weaponBehavior.useWeapon()

class WeaponBehavior(metaclass = ABCMeta):
    @abstractmethod
    def useWeapon(self):
        pass

class KnifeBehavior(WeaponBehavior):
    def useWeapon(self):
        print('서걱')

class BowAndArrowBehavior(WeaponBehavior):
    def useWeapon(self):
        print('푱')

class AxeBehavior(WeaponBehavior):
    def useWeapon(self):
        print('쾅')

class SwordBehavior(WeaponBehavior):
    def useWeapon(self):
        print('슝')

queen = Queen()
queen.fight()
queen.setWeapon(BowAndArrowBehavior())
queen.fight()

troll = Troll()
troll.fight()
troll.setWeapon(KnifeBehavior())
troll.fight()

king = King()
king.fight()


This post is licensed under CC BY 4.0 by the author.