ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [패턴] 전략(Strategy) 패턴
    카테고리 없음 2024. 3. 26. 11:28

    TMI

    최근에 코드를 짜는데 전략 패턴이 생각나서 전략 패턴을 적용하여 코드를 짜봤다.

    아주 간단한 기능이어서 굳이 쓸까 싶었지만 한번 쯤 사용하면 이해되는데 도움이 될거 같아서 사용해봤다.


    언제 사용 하는지?

    • 같은 결과를 반환하는 동작이지만 내부 코드가 다를 때
    • 동작이 런타임 중에 실시간으로 교체되어야 할 때

    전략 패턴을 사용하지 않은 예시 코드

    enum class Type {
        ITEMSADDER,
        MATERIAL
    }
    
    data class Tool(
        private val id: String
    ) {
    
        // Enum을 이용하여 비교하기 때문에 추후에 타입 추가가 필요하면 Tool 클래스를 수정해야할 것이다.
        fun isTool(itemStack: ItemStack, type: Type): Boolean {
        	return when (type) {
                ITEMSADDER -> CustomStack.byItemStack(itemStack)?.id == id
                MATERIAL -> itemStack.type == Material.matchMaterial(id.uppercase())
            }
        }
    }

     

    전략 패턴을 사용한 예시 코드

    이렇게 원하는 Strategy로 바꿔서 사용할 수 있게 된다.

    도구를 비교하는 구문을 ToolStrategy에 위임하여 유지보수가 쉽고

    추후 다른 API를 추가하여 비교하고 싶을 때 추가가 쉬운 구조가 되었다.
    (Tool 클래스를 전혀 수정하지 않고 상속만 시켜서 만들 수 있게 된다.)

    (아래는 이전에 만들었던 코드 일부분을 가져왔다.)

    interface ToolStrategy {
        // 둘다 ItemStack과 id로 비교할 수 있기 때문에 ToolStrategy로 인터페이스를 만들었다.
        fun isTool(itemStack: ItemStack, id: String): Boolean
    }
    
    class ItemsAdderStrategy : ToolStrategy {
        // 외부 API를 받아 도구인지 체크하는 구문
        override fun isTool(itemStack: ItemStack, id: String): Boolean {
            println("외부 API로 비교")
            return CustomStack.byItemStack(itemStack)?.id == id
        }
    }
    
    class MaterialStrategy : ToolStrategy {
        // 기본 API를 받아 도구인지 체크하는 구문
        override fun isTool(itemStack: ItemStack, id: String): Boolean {
            println("기본 API로 비교")
            return itemStack.type == Material.matchMaterial(id.uppercase())
        }
    }
    data class Tool(
        private val id: String
    ) {
    
        // 기본 API로 작동하는 MaterialStrategy로 변수 초기화
        private var toolStrategy: ToolStrategy = MaterialStrategy()
    
        // ToolStrategy를 상속하는 클래스면 모두 비교할 수 있게 된다.
        fun isTool(itemStack: ItemStack): Boolean {
            return toolStrategy.isTool(itemStack, id)
        }
    
        // 원하는 ToolStrategy로 변경할 수 있다.
        fun setToolStrategy(toolStrategy: ToolStrategy) {
        	this.toolStrategy = toolStrategy
        }
    }
    fun main() {
        val itemStack = ItemStack(Material.DIAMOND_PICKAXE)
        val tool = Tool("diamond_pickaxe")
        if (tool.isTool(itemStack)) { // 출력: 기본 API 비교
        	// TODO
        }
        tool.setToolStrategy(ItemsAdderStrategy())
        if (tool.isTool(itemStack)) { // 출력: 외부 API 비교
        	// TODO
        }
    }
Designed by Tistory.