개발/GO

[Golang] 전략(Strategy) 패턴

피클s 2022. 4. 1. 16:46

이 글은 헤드퍼스트 디자인패턴을 Golang으로 표현한 글입니다.

 

목차

     

    1. 전략 패턴의 정의

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

    이게 뭔 개소리야.

     

    쉬운 말로 하면 자주 변경되는 부분과 변하지 않는 부분을 분리하여 관리하자! 입니다.

    고객의 요구, 사양변경 등의 이유로 발생하는 변화에 유연하게 대응하기 위한 설계입니다.

     

    2. 핵심 원칙

    1. 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분과 분리한다.
    2. 상속보다는 구성을 확용한다. (Golang에는 상속이 없습니다.)
    3. 구현보다는 인터페이스에 맞춰서 프로그래밍한다.

     

    3. 오리 문제

    3-1. 스펙

    • 모든 오리는 수영할 수 있다.
    • 청둥오리는 날 수 있다.
    • 청둥오리는 꽥꽥 소리 낸다.
    • 고무오리는 날 수 없다.
    • 고무오리는 삑삑 소리 낸다.

     

    3-2. 구현

    변경되지 않는 부분 : 수영

    자주 변경되는 부분 : 날아다니는 기능, 소리내는 기능

     

    오리

    type Flybehavior interface {
    	fly()
    }
    type QuackBehavior interface {
    	quack()
    }
    
    type Duck struct {
    	name          string
    	flyBehavior   Flybehavior
    	quackBehavior QuackBehavior
    }
    
    func (d Duck) swim() {
    	fmt.Println("발발발발")
    }
    
    func (d Duck) display() {
    	fmt.Printf("나는 %s !!\n", d.name)
    }
    
    func (d Duck) performQuack() {
    	d.quackBehavior.quack()
    }
    
    func (d Duck) performFly() {
    	d.flyBehavior.fly()
    }

    새로운 오리가 추가될 때마다 나는 기능과 소리치는 기능은 조금씩 다르게 정의될 것이라고 예상된다고 가정합니다.

    이때 인터페이스로 정의하여 각 오리에 맞게 유연하게 새 기능을 추가할 수 있도록 합니다.

     

     

     

    푸드득

    type FlyWithWings struct{}
    
    func (f FlyWithWings) fly() {
    	fmt.Println("오리 날다")
    }
    
    type FlyNoWay struct{}
    
    func (f FlyNoWay) fly() {
    	fmt.Println("못 나는 오리")
    }

     

    꽥꽥

    type Quack struct{}
    
    func (q Quack) quack() {
    	fmt.Println("꽥꽥")
    }
    
    type Squeak struct{}
    
    func (s Squeak) quack() {
    	fmt.Println("삑삑")
    }

     

    실행

    func main() {
    	mallardDuck := Duck{
    		name:          "청둥오리",
    		flyBehavior:   FlyWithWings{},
    		quackBehavior: Quack{},
    	}
    
    	mallardDuck.swim()
    	mallardDuck.display()
    	mallardDuck.performQuack()
    	mallardDuck.performFly()
    
    	fmt.Println("============")
    
    	rubberDuck := Duck{
    		name:          "고무오리",
    		flyBehavior:   FlyNoWay{},
    		quackBehavior: Squeak{},
    	}
    
    	rubberDuck.swim()
    	rubberDuck.display()
    	rubberDuck.performQuack()
    	rubberDuck.performFly()
    }
    발발발발
    나는 청둥오리 !!
    꽥꽥
    오리 날다
    ============
    발발발발
    나는 고무오리 !!
    삑삑
    못 나는 오리

     

     

    4. 소감

    Golang은 객체지향 언어가 아니기 때문에 책내용 그대로 구현하는 것에는 어려움이 있군요..