본문 바로가기
아이폰 개발/디자인 패턴

swift 디자인패턴 - Strategy Pattern

by 인생여희 2021. 8. 22.

swift 디자인패턴 - Strategy Pattern

 

언제 사용하나?

어떤 상황에서 사용할 알고리즘이 여러개 존재할때 사용한다.

알고리즘을 런타임에서 변경해야 할때 사용한다.

예) 결제를 할때 결제 수단 선택하기 - 신용카드로 결제, 마일리지로 결제, 포인트로 결제, 쿠폰으로 결제 등등

검색할때 검색 조건 선택하기 - 전체검색, 이미지검색, 뉴스 검색 등등

 

장점 

런타임에서 알고리즘을 변경 할 수 있다.

알고리즘을 사용하는 코드와 알고리즘을 구현하는 코드를 분리할 수 있다.

알고리즘을 사용하는 코드 context를 변경하지 않고도 새로운 전략 기능을 추가 할 수 있다.

 

단점

알고리즘이 몇개 없을때 복잡성을 증가 시킬수 있다.

strategy, context간 통신오버헤드가 발생한다.

 

 

목표

인터페이스 개념을 이해한다. 델리게이트 개념을 이해한다. 전력 패턴 개념을 이해한다.

 

인터페이스?

키보드나 디스플레이 처럼 사람과 컴퓨터를 연결하는 장치이다.

두 객체를 연결시키는 접점.

기능에 대한 선언과 구현이 분리가 되어 있다.

기능을 통로로 사용할 수 있다.

 

델리게이트?

델리게이트 : 위임하다, 떠넘기다. 두객체간의 관계에서 나타난다.

특정객체의 기능을 사용하기 위해 다른 객체의 기능을 호출하는 것.

 

예제 1

 

전략패턴

여러 알고리즘을 하나의 추상적인 접근점을 만들어 접근점에서 서로 교환 가능하도록 하는 패턴

 

요구사항

게임에서 캐릭터와 무기를 구현해보시오

무기는 두가지 종류가 있다. 

-칼, -검

캐릭터는 무기를 칼을 선택할 수도 있고, 검을 선택할 수도 있다.

 

import Foundation


/// 전략 인터페이스
protocol Weapon {
    func attack()
}
/// 칼 공격 전략
class Knife : Weapon {
    func attack() {
        print("칼 공격")
    }
}
/// 손공격 전략
class Hand : Weapon {
    func attack() {
        print("손 공격")
    }
}

/// 전략 패턴 클래스를 사용할 주체 클래스
class GameCharacter {
    /// 접근점 - 사용할 무기
    private var weapon : Weapon?
    
    /// 무기 교환 가능
    func setWeapon(weapon : Weapon){
        self.weapon = weapon
    }
    /// 공격
    func attack() {
        if weapon == nil {
            print("36계 줄행랑")
        }else{
            /// 델리게이트
            /// GameCharacter 는 무기 사용하는 기능을 Weapon 에 위임했다.
            weapon?.attack()
        }
    }
}


let character = GameCharacter()
character.attack()                      //36계 줄행랑
character.setWeapon(weapon: Hand())
character.attack()                      //손 공격

 

 

예제 2

 

 

Context : Strategy 객체를 소유하고 동적으로 행위를 실행하는 객체

 

Strategy : ConcreteStrategy 객체의 부모 객체로서 동적으로 지정할 행위에 대한 알고리즘 인터페이스를 정의 하는 추상객체

 

ConcreteStrategy : Strategy 인터페이스를 구현한 객체

 

 

import Foundation

/// 전략 패턴
protocol Strategy{
    func doAlgorithm <T: Comparable> (data:[T]) -> [T]
}

/// 전략 A - 순서대로 정렬시키기 알고리즘
class ConcreteStrategyA : Strategy {
    func doAlgorithm<T>(data: [T]) -> [T] where T : Comparable {
        return data.sorted()
    }
}

/// 전략 B - 반대로 정렬시키기 알고리즘
class ConcreteStrategyB : Strategy {
    func doAlgorithm<T>(data: [T]) -> [T] where T : Comparable {
        return data.sorted(by: >)
    }
}

class Context {
    
    //접근점 - 프로토콜
    private var strategy: Strategy
    
    init(strategy: Strategy) {
        self.strategy = strategy
    }
    /// 교환 가능
    func update(strategy:Strategy){
        self.strategy = strategy
    }
    
    func doBusinessLogic(){
        /// 델리게이트
        /// Context 는  정렬 기능을 Strategy 에 위임했다.
        let result = strategy.doAlgorithm(data: ["a", "b","c","d","e","f"])
        print(result.joined(separator: ","))
    }
}

/// 사용
/// 순서대로 정렬
let context = Context(strategy: ConcreteStrategyA())
context.doBusinessLogic()

/// 반대로 정렬
context.update(strategy: ConcreteStrategyB())
context.doBusinessLogic()

 

 

참고

https://icksw.tistory.com/259

https://joycestudios.tistory.com/