Pola Factory
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Kotlin di Coddy. Pelajaran 43 dari 57.
Pola factory menempatkan keputusan tentang class mana yang akan dibuat di satu tempat. Pemanggil menjelaskan kebutuhannya dan menerima tipe interface, tanpa menyebut nama class konkret:
interface Notifier {
fun send(to: String): String
}
class EmailNotifier : Notifier {
override fun send(to: String) = "email to $to"
}
class SmsNotifier : Notifier {
override fun send(to: String) = "sms to $to"
}
object NotifierFactory {
fun create(channel: String): Notifier? = when (channel) {
"email" -> EmailNotifier()
"sms" -> SmsNotifier()
else -> null
}
}Di dalam main:
println(NotifierFactory.create("sms")?.send("ada"))
println(NotifierFactory.create("fax")?.send("bo"))Output:
sms to ada
nullDi Kotlin, factory sering berupa fungsi di companion object dari interface atau base class, sehingga pemanggil menulis Shape.from("circle 2"). Factory dapat mengurai dan memeriksa input sebelum membuat apa pun:
interface Shape {
fun area(): Double
companion object {
fun from(text: String): Shape? {
val p = text.split(" ")
val n = p.getOrNull(1)?.toDoubleOrNull() ?: return null
return when (p[0]) {
"circle" -> Circle(n)
"square" -> Square(n)
else -> null
}
}
}
}
class Circle(val r: Double) : Shape {
override fun area() = 3.14 * r * r
}
class Square(val s: Double) : Shape {
override fun area() = s * s
}Di dalam main:
println(Shape.from("square 3")?.area())
println(Shape.from("circle x")?.area())Output:
9.0
nullPemanggil hanya melihat antarmuka, jadi factory dapat mengubah class yang dikembalikannya tanpa mengubah pemanggil. Di sini, data kecil disimpan di memori dan data besar disimpan ke disk:
interface Storage {
fun describe(): String
}
class MemoryStorage : Storage {
override fun describe() = "memory"
}
class DiskStorage(val path: String) : Storage {
override fun describe() = "disk at $path"
}
fun storageFor(sizeMb: Int): Storage = if (sizeMb < 100) MemoryStorage() else DiskStorage("/tmp/cache")Di dalam main:
println(storageFor(5).describe())
println(storageFor(500).describe())Output:
memory
disk at /tmp/cacheFactory juga bisa berupa nilai: fungsi bertipe (String) -> Animal membuat object tanpa pemanggil mengetahui class-nya. Map dari nama ke fungsi semacam itu disebut registry, dan referensi konstruktor seperti ::Dog adalah fungsi factory siap pakai:
open class Animal(val name: String) {
open fun sound() = "..."
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Woof"
}
class Cat(name: String) : Animal(name) {
override fun sound() = "Meow"
}Di dalam main:
val makers: Map<String, (String) -> Animal> = mapOf("dog" to ::Dog, "cat" to ::Cat)
val pet = makers.getValue("cat")("Tom")
println("${pet.name} says ${pet.sound()}")Output:
Tom says MeowTantangan
MudahBeberapa exporter mengimplementasikan interface Exporter yang disediakan (extension dan export(title, lines)). Tulis MarkdownExporter (extension md: satu baris # Title dan satu baris - item untuk setiap baris), CsvExporter (extension csv: title,Title, lalu line,item untuk setiap baris), dan PlainExporter (extension txt: judul dalam huruf kapital, lalu baris-baris tanpa perubahan). Kemudian tulis object factory ExporterFactory: create(format) mengembalikan exporter untuk markdown, csv, atau plain, tanpa membedakan huruf besar dan kecil, atau null, dan supported() mengembalikan nama format.
Kode yang disediakan membaca format, judul, dan baris-baris, lalu mencetak report.md dan teks yang diekspor, atau unsupported format pdf; try markdown, csv, plain.
Tulis kodemu di MarkdownExporter.kt, CsvExporter.kt, PlainExporter.kt, ExporterFactory.kt, dan Exporter.kt. Main.kt berisi kode input/output yang disediakan dan tidak dapat diedit.
Coba sendiri
fun main() {
// Kode input/output yang disediakan: biarkan tetap seperti ini
val input = generateSequence(::readLine).toList()
val exporter = ExporterFactory.create(input[0])
if (exporter == null) {
println("unsupported format ${input[0]}; try ${ExporterFactory.supported().joinToString(", ")}")
} else {
println("report.${exporter.extension}")
println(exporter.export(input[1], input.drop(2)))
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1class dan object
Bekerja dengan fileMendefinisikan classKonstruktor utamaBlok init dan validasiKonstruktor sekunderRingkasan: Kartu Perpustakaan2property dan Enkapsulasi
Accessor KustomModifier VisibilitasSetter Privatlazy dan lateinitRingkasan: Rekening Bank5Interface
Mendeklarasikan Interfacemethod DefaultBeberapa InterfaceInterface sebagai TipeUlasan: Metode Pembayaran11Proyek: Pengelolaan Perpustakaan
Buku dan AnggotaPeminjaman BukuLatihan sendiri: Playground Kotlin