빌더 패턴을 사용하여 중첩 된 목록을 작성하려면 어떻게해야합니까?

Nov 30 2020

빌더 패턴을 사용하여 GraphQL 구문에 대한 쿼리 빌더를 만들려고합니다. 나는 이미 필터링 부분을 위해 그것을했다.

쿼리에서 되돌리고 싶은 데이터 를 프로그래밍 방식으로 말하고 싶습니다. (참고 : title쿼리 의 일부가 QueryBuilder에 하드 코딩 되기 전 .

이를 위해 속성으로 자체 목록이있는 Entity라는 클래스를 만들었습니다.

class Entity(
        private val entity: EntityType,
        private val entities: MutableList<Entity> = mutableListOf()
) {
    override fun toString(): String {
        return if (this.entities.isEmpty()) {
            entity.str
        } else {
            this.entity.str + "{" + this.entities.onEach {
                it.toString()
            }.joinToString(" ") + "}"
        }
    }
}

그리고 나는 그것을 작동시켰다. 그러나 구조를 구축합니다. 그런 다음 목록에 추가하고 해당 목록의 항목을 방문하려면 항목 목록을 "방문"해야합니다.

예를 들어이 쿼리를 작성하려는 경우 :

{
  events(place:"Somewhere", area:"The place"){
    title
    location{
      coordinates{
        longitude
        latitude
      }
    }
  }
}

그런 다음 엔티티의 레이어에서 두 단계 아래로 내려 가야합니다. 그리고 지금하는 방식으로 코드가 매우 넓어집니다.

fun main() {
    val e1 = listOf<Entity>(
            Entity(EntityType.TITLE),
            Entity(EntityType.LOCATION,
                    mutableListOf(
                            Entity(EntityType.COORDINATES,
                                    mutableListOf(
                                            Entity(EntityType.LONGITUDE),
                                            Entity(EntityType.LATITUDE)
                                    )
                            )
                    )
            )
    )

    val q1 = Query.Builder()
            .filter(FilterType.PLACE, "Somewhere")
            .filter(FilterType.AREA,"The place")
            .add(e1)
            .build()
    println(q1.query)
}

그래서 빌더 패턴을 사용할 생각이었습니다. 또는 더 똑똑해질 다른 것.

도움을 주셔서 미리 감사 드리며 좋은 하루 되세요.

BTW : 다음 열거 형을 사용하고 있습니다.

enum class EntityType(val str: String) {
    EVENTS("events"),
    TITLE("title"),
    LOCATION("location"),
    COORDINATES("coordinates"),
    LONGITUDE("longitude"),
    LATITUDE("latitude"),
}

enum class Filter(val str: String) {
    PLACE("place"),
    AREA("area"),
}

나머지 코드는 다음과 같습니다.

class Filter {
    var filters = mutableMapOf<FilterType, Any>()
    override fun toString(): String {
        return if (filters.isNotEmpty()) {
            "(" + filters.map {
                if (it.value is Int || it.value is Long) {
                    it.key.str + ":" + it.value + ","
                } else {
                    it.key.str + ":\"" + it.value + "\","
                }
            }.joinToString(" ").dropLast(1) + ")"
        } else {
            ""
        }
    }
}

class Query private constructor(val query: String) {
    class Builder {
        private lateinit var entities: List<Entity>
        private var filter = Filter()

        fun filter(key: FilterType, value: Any) = apply {
            this.filter.filters[key] = value
        }

        fun add(entities: List<Entity>) = apply {
            this.entities = entities
        }

        private fun collect(root:String):String {
            return "{$root$filter{${entities.joinToString(" ")}}}"
        }

        fun build(): Query {
            return Query(collect("events"))
        }
    }

답변

1 Pelocho Dec 01 2020 at 10:48

Kotlin Type-Safe Builders 문서를 살펴보세요 . HTML에서 수행하는 방법에 대한 예제를 찾을 수 있습니다.