Pengertian Design Pattern Prototype adalah bagian dari creational design pattern yang memungkinkan kamu menyalin object yang ada tanpa membuat kodemu bergantung pada class yang disalin. Prinsip Design Pattern ini merupakan salah satu turunan dari Creational Pattern. Prototype Design Pattern adalah konsep membuat objek dengan cara melakukan cloning pada objek yang sudah tersedia. Karena terkadang membuat objek baru memakan banyak resource di memori. Umumnya untuk membuat objek serupa kamu perlu melakukan inheritance yang terkadang akan menciptakan hierarki kompleks sehingga menyulitkan untuk melakukan tracing method. Fungsi ini turunan dari kelas yang mana? Dengan menerapkan prototype pattern, manfaatnya adalah kita dapat menyederhanakan sebuah objek yang menggunakan inheritance sangat kompleks, menjadi lebih flat.

Permasalahan Arsitektur Code

Misal ada sebuah object, Anda ingin untuk membuat duplikat yang sama persis dari object tersebut. Cara pertama yang terpikirkan adalah untuk membuat object baru dari class yang sama (Object objekbaru = new Object()). Lalu, mengisi setiap fields / parameter dari object yang ingin diduplikat dan meduplikat setiap values dari object baru tersebut.

Tapi, apabila menggunakan cara seperti ini, terdapat masalah yang tak terlihat. Tidak semua objects dapat disalin menggunakan cara tersebut karena beberapa fields dari object tesebut mungkin ada yang di private sehingga tidak dapat diakses dari luar object tersebut.

Prototype Design Pattern menjadi solusi arsitektur struktur data misalnya:

  1. Mencegah deklarasi value dari field objek satu-persatu, hanya agar mempunyai field yang serupa dengan objek yang ingin ditiru.
  2. Melakukan cloning sampai ke field yang sedang diprivat sekaligus

Solusi Melakukan Duplikat Objek

Design Pattern Prototype bertujuan untuk melakukan proses duplikasi dari suatu object menjadi object baru yang serupa. Jadi, pattern ini mendeklarasikan suatu interface untuk tiap object yang support untuk melakukan cloning. Interface ini bertujuan untuk membolehkan Kamu untuk menduplikasi suatu object tanpa coupling dari kode kamu terhadap class dari object tersebut. Biasanya, interface tersebut hanya berisi satu method yaitu clone​.

UML Design Pattern Prototype

Perhatikan tampilan diagram UML Prototype Pattern ini

UML of Design Pattern Prototype Principle

Interface Prototype akan berisi abstract method umum yang wajib ada untuk dalam objek cloning (semisal mobil wajib meniru fitur roda). Kita bisa menggunakan method bawaan cloneable, namun dengan membuat interface prototype ini, kamu dapat mencegah tight coupling ketika melakukan copy ke ConcretePrototype atau salinan-salinan prototype. Sedangkan ConcretePrototype akan melakukan extends dari Prototype interface dengan melakukan override dari Clone method

Contoh case kapan menggunakan Creational Design Pattern Prototype

Contoh case dimana kita perlu menggunakan prototype adalah konsep multi role dimana membuat objek dengan role yang berbeda bisa sangat berat, bayangkan masing-masing objek perlu mengakses database dan konfigurasi yang memerlukan komunikasi di luar aplikasi secara terpisah. Tentu menjadi isu performa bagi aplikasi. Terus, bagaimana prototype berguna pada case multi role ini?


Kita menentukan main objek yang akan digunakan sebagai prototipe, isinya adalah apa yang menjadi kesamaan dari setiap objek. Misal role, maka masukkan ke dalam kelas prototipe. Anggap isinya tentang access control, kemudian objek prototipe itu kita implementasikan clone method juga. Kemudian dibuat kelas role, seperti admin, student (Siswa, Mahasiswa), pengajar (Dosen, Guru), dll yang akan mengimplementasi salinan dari kelas prototipe yang berisi access control tersebut.

Tahapan Implementasi Prototype Design Pattern

Jadi sebenarnya seperti apa konsep design pattern prototype dapat dilihat dalam list berikut:

  • Membuat objek melalui menyalin objek yang tersedia
  • Objek yang bertindak sebagai prototype bekerja dengan mengelola state dari objek
  • Kotlin dan Java punya fitur ini, yaitu dengan memanggil Clone method, yang merupakan tipe interface

Langkah pertama, buat interface Objek yang memiliki method clone.

Kalau kita memakai method Clone bawaan dari kotlin (Cloneable interface), ini bersifat shallow clone karena sebenarnya hanya bertindak sebagai reference tetapi tidak mengerjakan cloning yang sesungguhnya dari objek yang menjadi implement dibaliknya. Dengan membuat objek interface tersendiri (deep clone) kamu menerapkan single responsibility principle dalam memanage kelas prototipe dan lebih mudah untuk implementasi Cloning.

interface Prototype {
   fun clone(): Prototype
   /*Add other universal field of prototype here
   * */
}

Langkah kedua, buat ekstensi dari Prototype, yaitu bentuk lebih real atau konkrit dari prototype, misal untuk prototipe kendaraan, kita akan extend dalam kelas kendaraan roda dua. Jika ingin membuat clone berbeda, cukup buat concrete prototype kedua, misal kendaraan roda empat.

class FirstConcretePrototype : Prototype {
    var name: String
        private set

    constructor(name: String) {
        this.name = name
    }

    constructor(prototype: FirstConcretePrototype) {
        name = prototype.name
    }

    override fun clone(): Prototype {
        return FirstConcretePrototype(this)
    }
}

Buat Objek Concrete Kedua

class SecondaryConcretePrototype : Prototype {
    var number: Int
        private set

    var name: String = ""

    constructor(name: String, id: Int){
        this.name = name
        this.number = id
    }

    constructor(id: Int){
        this.number = id
    }

    override fun clone(): Prototype {
        return SecondaryConcretePrototype(name, number)
    }
}

Kemudian buat Kelas ProtototypeRegistry bertugas sebagai penyimpanan instance objek hasil clone yang dibuat.

class PrototypeRegistry {
    private val prototypeRegistry: MutableMap<String, Prototype>

    init {
        prototypeRegistry = HashMap()
    }

    fun addPrototypeToRegistory(prototypeName: String, prototype: Prototype) {
        prototypeRegistry[prototypeName] = prototype
    }

    fun getPrototypeCloneFromPrototypeRegistory(name: String): Prototype {
        return prototypeRegistry[name]!!.clone()
    }
}

Kamu juga dapat membuat get prototypefactory method didalam kelas registry untuk mereturn objek clone sehingga kamu dapat mengakses kembali hasil clone di tempat lain. Atau mungkin kamu ingin membuat sebuah clone yang terdiri dari beberapa gabungan clone objek, kamu bisa membuat class factory terpisah dari class registry. Pada kode diatas, prototypeRegistry berfungsi untuk menyimpan objek yang akan diclone.

Sedangkan GetPrototypeCloneFromPrototypeRegistory ini akan mereturn clone objek yang telah disimpan.

Pada client lakukan pemanggilan concrete object

class Client {
    companion object{
        @JvmStatic
        fun main(args: Array<String>) {
            val prototype = FirstConcretePrototype("Test name")
            val registory = PrototypeRegistry()
            registory.addPrototypeToRegistory("Original", prototype)
            val clone = registory.getPrototypeCloneFromPrototypeRegistory("Original") as FirstConcretePrototype

            println("$prototype is ${prototype.name}")
            println("$clone is cloning ${clone.name}")

            val secondaryPrototype = SecondaryConcretePrototype("second test", 1)
            registory.addPrototypeToRegistory("Second", secondaryPrototype)
            val secondClone = registory.getPrototypeCloneFromPrototypeRegistory("Second") as SecondaryConcretePrototype

            println("$secondaryPrototype is ${secondaryPrototype.name} has ${secondaryPrototype.number}")
            println("$secondClone is copy of ${secondClone.name}")

        }
    }
}

Pada kode client, terdapat inisialisasi object Prototype yaitu val prototype, kemudian disimpan dalam variable clone bernama registory. Sehingga dibandingkan menginisiasi kembali objek, kamu bisa meminta registory untuk mengakses objek clone dari prototype.

Kotlin Creational Design Pattern, Demo of implementation of Prototype Design Pattern

Jika kalian lihat objek concrete dan clonningan dari objek concrete mempunyai referensi objek yang berbeda. Tetapi masing-masing value di baik objek concrete dan salinnya ternyata sama. Coba lihat val prototype hasil getname nya sama seperti value getname dari objek clone.

val prototype = FirstConcretePrototype("Test name")
            val registory = PrototypeRegistry()
            registory.addPrototypeToRegistory("Original", prototype)
            val clone = registory.getPrototypeCloneFromPrototypeRegistory("Original") as FirstConcretePrototype

            println("$prototype is ${prototype.name}")
            println("$clone is cloning ${clone.name}")

Demo Kode implementasi untuk Real Case Design Pattern Prototype

Sekarang, kita coba pada demo kedua, yaitu kasus file ekstraksi, misal ekstraksi file berbeda satu dengan lain tergantung dengan ekstensi. Di sini Prototipe Object adalah Archiver dengan Concrete Object adalah ZipArchiver dan RarArchiver.

Buat Kelas Interface Prototype dengan nama Archive, deklarasikan abstract method yang dapat dicloning

interface Archive {
    fun archive(directory: File?)
    fun clone(): Archive
}

ConcretePrototype

class RarArchiver : Archive {
    override fun archive(directory: File?) {
        println("Rar archiver + ${directory!!.path}")
    }

    override fun clone(): Archive {
        return RarArchiver()
    }
}
class ZipArchiver : Archive, Serializable {
    override fun archive(directory: File?) {
        println("Zip Archiver + ${directory!!.path}")
    }

    override fun clone(): Archive {
        return ZipArchiver()
    }
}

Factory

object ArchiveFactory {
    private val prototypes: MutableMap<String, Archive> = HashMap()

    init {
        prototypes["zip"] = ZipArchiver()
        prototypes["rar"] = RarArchiver()
    }

    fun getPrototypeForType(archiverType: String): Archive {
        return prototypes[archiverType]!!.clone()
    }
}

Kelas ini akan menyimpan objek yang kompatible dengan Archiver. Dengan masing-masing disimpan dalam Mutablemap sehingga untuk memanggil prototipe yang dibutuhkan cukup dengan memanggil keynya.

class Demo {
    companion object{
        @JvmStatic
        fun main(args: Array<String>) {
            val archiverType1 = "zip"
            val archiverType2 = "rar"
            val zipArchiver: Archive = ArchiveFactory.getPrototypeForType(archiverType1)
            val rarArchiver: Archive = ArchiveFactory.getPrototypeForType(archiverType2)
            zipArchiver.archive(File("Subscribe to FB, IG, and YT"))
            rarArchiver.archive(File("of nakotek (Wahaha)"))
        }
    }
}

Untuk versi advanced dari penggunaan prototype design pattern, kamu bisa lihat di Creational.Demo pada folder maze, download di sini.
Kesimpulan dari design pattern prototype ini adalah sebuah cara untuk membuat objek baru dengan menyalin objek yang sudah ada tanpa memodifikasi internal objek. Metode ini menjadi alternatif apabila membuat objek merupakan operasi yang “mahal”. Untuk tutorial struktur data lainnya, silahkan kunjungi link ini.

Join our list

Subscribe to our mailing list and get interesting stuff and updates to your email inbox.

Thank you for subscribing.

Something went wrong.


Like it? Share with your friends!

What's Your Reaction?

Unfortunate
0
Unfortunate
Meh
0
Meh
Wahaha
1
Wahaha
Nin nin
0
Nin nin
nakomin

Believe at the heart of BNRS

Here you will find content about developers needs whether it’s coding tutorials or the lifestyle of employee in the IT circle, understanding of the realm of ui/ux and futuristic tech for free in one place. Don’t forget to follow the nakotek socials to give the author enthusiasm in pioneering this website. #wahahaforever

0 Comments

Your email address will not be published. Required fields are marked *