Menu
Coddy logo textTech

Strateji Kalıbı

Coddy'nin Kotlin Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 45 / 57.

Strategy deseni, bir algoritmanın her varyantını ortak bir arayüzün arkasında kendi sınıfına yerleştirir. Onu kullanan kod bir strateji tutar ve program çalışırken bu stratejiyi değiştirebilir:

interface Shipping {
    fun cost(kg: Int): Int
}
class Standard : Shipping {
    override fun cost(kg: Int) = 5 + kg
}
class Express : Shipping {
    override fun cost(kg: Int) = 15 + kg * 2
}

class Checkout(var shipping: Shipping) {
    fun total(price: Int, kg: Int) = price + shipping.cost(kg)
}

main içinde:

val checkout = Checkout(Standard())
println(checkout.total(100, 3))
checkout.shipping = Express()
println(checkout.total(100, 3))

Çıktı:

108
121

Bir stratejinin tek bir metodu olduğunda, bir işlev türü yeterlidir. Sınıf bir işlevi saklar ve onu çağırır:

class Formatter(var style: (String) -> String) {
    fun show(words: List<String>) = words.joinToString(" ") { style(it) }
}

main içinde:

val f = Formatter { it.uppercase() }
println(f.show(listOf("hello", "world")))
f.style = { it.reversed() }
println(f.show(listOf("hello", "world")))

Çıktı:

HELLO WORLD
olleh dlrow

Bir strateji, algoritmanın içindeki bir when ifadesinin yerini alır. when kullanıldığında, her yeni seçenek algoritmanın düzenlenmesi anlamına gelir. Stratejilerde ise yeni bir seçenek, yeni bir sınıf veya lambda demektir ve Checkout asla değişmez:

// strateji olmadan: her yeni seçenek bu fonksiyonu düzenler
fun cost(kind: String, kg: Int) = when (kind) {
    "standard" -> 5 + kg
    else -> 15 + kg * 2
}
// strateji ile: bir sınıf ekle, Checkout'u olduğu gibi bırak
class Overnight : Shipping {
    override fun cost(kg: Int) = 40
}

Bir strateji genellikle bir müşterinin planı gibi verilerden, bir eşleme veya küçük bir fabrika kullanılarak seçilir:

val discounts: Map<String, (Int) -> Int> = mapOf(
    "gold" to { price -> price * 80 / 100 },
    "silver" to { price -> price * 90 / 100 }
)

fun finalPrice(plan: String, price: Int) = discounts[plan]?.invoke(price) ?: price

main içinde:

println(finalPrice("gold", 200))
println(finalPrice("silver", 200))
println(finalPrice("basic", 200))

Çıktı:

160
180
200
challenge icon

Görev

Kolay

Bir kahramanın saldırısı bir stratejidir. Attack arayüzü (name ve damage(strength) ile birlikte) sağlanmıştır. Sword (gücün 2 katı hasar), Bow (gücün 5 fazlası) ve Magic(mana) (mana en az 10 olduğunda gücün 3 katı, aksi takdirde 1) yazın. Hero(name, strength, attack), attack değerini istediği zaman değiştirebilir ve strike(), hangi saldırıya sahip olduğunu kontrol etmeden Ada hits with sword for 20 döndürür.

Sağlanan kod name,strength bilgisini okur ve ardından equip bow, equip magic 15, equip sword veya strike komutlarını işler; her saldırının sonucunu yazdırır.

Kodunuz Sword.kt, Bow.kt, Magic.kt, Hero.kt ve Attack.kt dosyalarına yazılmalıdır. Main.kt, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

fun main() {
    // Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
    val input = generateSequence(::readLine).toList()
    val (name, strength) = input[0].split(",")
    val hero = Hero(name, strength.toInt(), Sword())
    for (cmd in input.drop(1)) {
        val p = cmd.split(" ")
        if (p[0] == "strike") {
            println(hero.strike())
            continue
        }
        hero.attack = when (p[1]) {
            "bow" -> Bow()
            "magic" -> Magic(p[2].toInt())
            else -> Sword()
        }
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Kotlin playground