Strategy — apa itu, pola strategi di iOS dan Android

Penulis: IT Sectr Diterbitkan: 2026-02-18 Waktu membaca: 9 mnt

Strategy (Strategi) — pola desain perilaku yang mendefinisikan keluarga algoritma yang dapat dipertukarkan dan menempatkan masing-masing ke dalam kelas terpisah (Strategy). Pola ini memungkinkan pemilihan algoritma dengan cepat: kode klien bekerja melalui antarmuka Strategy bersama, dan implementasi konkret dimasukkan saat runtime. Di iOS pola diimplementasikan melalui Protocol + kelas strategi, di Android — melalui Interface + implementasi. Strategy — salah satu dari 23 pola GoF, banyak digunakan untuk pemrosesan pembayaran, validasi, pengurutan, dan pemfilteran data. Selengkapnya — di deskripsi asli GoF.

Poin Penting

  • Strategy — pola perilaku GoF untuk keluarga algoritma yang dapat dipertukarkan
  • Enkapsulasi algoritma — setiap algoritma diisolasi dalam kelasnya sendiri
  • Antarmuka Strategy — kontrak bersama yang diimplementasikan oleh semua strategi konkret
  • Komposisi daripada pewarisan — konteks menyimpan referensi ke strategi, tidak mewarisi perilaku
  • Prinsip Open/Closed — strategi baru ditambahkan tanpa mengubah kode yang ada

Apa itu pola Strategy: esensi dan struktur

Strategy — salah satu dari 23 pola GoF (Gang of Four), dijelaskan dalam buku «Design Patterns: Elements of Reusable Object-Oriented Software» (1994). Pola ini memecahkan masalah pemilihan algoritma saat runtime. Alih-alih menulis satu kelas dengan banyak operator kondisional (if-else, switch), Strategy mengusulkan untuk memisahkan setiap algoritma ke dalam kelas terpisah dengan antarmuka bersama. Konteks (kelas yang menggunakan strategi) menyimpan referensi ke antarmuka Strategy dan mendelegasikan eksekusi ke strategi konkret.

Struktur pola mencakup tiga elemen: Context (konteks) berisi referensi ke Strategy dan memanggil metodenya; Strategy (antarmuka) mendeklarasikan metode bersama untuk semua algoritma; ConcreteStrategy (strategi konkret) mengimplementasikan antarmuka dan berisi algoritma konkret. Klien membuat strategi yang diperlukan dan meneruskannya ke konteks melalui konstruktor, setter, atau parameter metode. Konteks tidak tahu strategi mana yang dijalankan — ia hanya bekerja dengan antarmuka.

KomponenPeranContoh
ContextBerisi referensi ke StrategyPaymentProcessor, Sorter
StrategyAntarmuka bersama untuk algoritmaProtocol PaymentStrategy
ConcreteStrategyImplementasi konkret algoritmaCardPayment, PayPalPayment

Prinsip Open/Closed — keuntungan utama Strategy. Sistem terbuka untuk perluasan (dapat menambahkan strategi baru) dan tertutup untuk modifikasi (tidak perlu mengubah kode konteks). Tanpa pola, penambahan algoritma baru memerlukan perubahan kelas yang ada, yang melanggar OCP dan meningkatkan risiko kesalahan regresi. Strategy juga mengurangi ukuran kelas: alih-alih kelas 200 baris dengan switch-case, Anda mendapatkan 6 kelas masing-masing 20 baris.

Strategy di iOS: implementasi di Swift dengan Protocol

Strategy di Swift diimplementasikan melalui Protocol (antarmuka strategi) dan kelas atau struktur strategi. Protokol Swift mendukung associated types dan generic constraints, yang memberikan fleksibilitas dalam merancang strategi. Konteks biasanya adalah kelas ViewModel atau layanan yang menerima strategi di init atau melalui properti. Pola ini banyak digunakan dalam proyek iOS untuk penanganan peristiwa, animasi, pemformatan data, dan strategi UI.

swift
// 1. Protocol Strategy
protocol PaymentStrategy {
    func pay(amount: Decimal) async throws -> PaymentResult
}

// 2. Strategi Konkret
struct CardPaymentStrategy: PaymentStrategy {
    let cardNumber: String
    let cvv: String

    func pay(amount: Decimal) async throws -> PaymentResult {
        // Mengirim permintaan ke API bank
        return PaymentResult(status: .success, transactionId: "tx_\(UUID())")
    }
}

struct PayPalPaymentStrategy: PaymentStrategy {
    let email: String

    func pay(amount: Decimal) async throws -> PaymentResult {
        // Pengalihan ke PayPal SDK
        return PaymentResult(status: .success, transactionId: "pp_\(UUID())")
    }
}

// 3. Context
class PaymentProcessor {
    private var strategy: PaymentStrategy

    init(strategy: PaymentStrategy) {
        self.strategy = strategy
    }

    func setStrategy(_: PaymentStrategy) {
        strategy = strategy
    }

    func processPayment(amount: Decimal) async throws -> PaymentResult {
        return try await strategy.pay(amount: amount)
    }
}

// Penggunaan
let processor = PaymentProcessor(strategy: CardPaymentStrategy(cardNumber: "4111...", cvv: "123"))
let result = try await processor.processPayment(amount: 99.99)

Strategy di SwiftUI — pola ini secara alami terintegrasi dengan MVVM. ViewModel berisi properti strategi dan memanggil metodenya saat tindakan pengguna. SwiftUI View menerima data melalui @Published atau @State — strategi menyembunyikan detail implementasi dari View. Misalnya, strategi validasi teks (emailValidator, phoneValidator) diubah tergantung pada jenis bidang input. Menggabungkan Strategy dengan SwiftUI memberikan fleksibilitas tanpa pewarisan dari UIKit.

Strategy di Android: implementasi di Kotlin dengan Interface

Strategy di Kotlin menggunakan Interface di tingkat bahasa dan antarmuka fungsional (SAM) untuk penyederhanaan. Kotlin mendukung lambda, yang memungkinkan penerusan algoritma sebagai fungsi tanpa mendeklarasikan kelas strategi terpisah. Di Android pola diterapkan di ViewModel dan Use Cases untuk mengisolasi algoritma pemuatan data, caching, dan penanganan kesalahan. Proyek Android dengan Clean Architecture menggunakan Strategy untuk menyuntikkan implementasi repositori yang berbeda tergantung pada flag (mock, real, cache).

kotlin
// 1. Interface Strategy
interface PaymentStrategy {
    suspend fun pay(amount: BigDecimal): PaymentResult
}

// 2. Strategi Konkret
class CardPaymentStrategy(
    private val cardNumber: String,
    private val cvv: String
) : PaymentStrategy {
    override suspend fun pay(amount: BigDecimal): PaymentResult {
        // API bank melalui Retrofit
        return PaymentResult(success = true, transactionId = "tx_${UUID.randomUUID()}")
    }
}

class PayPalPaymentStrategy(
    private val email: String
) : PaymentStrategy {
    override suspend fun pay(amount: BigDecimal): PaymentResult {
        // PayPal SDK integration
        return PaymentResult(success = true, transactionId = "pp_${UUID.randomUUID()}")
    }
}

// 3. Context
class PaymentProcessor(
    private val strategy: PaymentStrategy
) {
    fun setStrategy(strategy: PaymentStrategy): PaymentProcessor {
        return PaymentProcessor(strategy)
    }

    suspend fun processPayment(amount: BigDecimal): PaymentResult {
        return strategy.pay(amount)
    }
}

// Penggunaan di ViewModel
class CheckoutViewModel : ViewModel() {
    private var processor = PaymentProcessor(CardPaymentStrategy("4111...", "123"))

    fun payWithCard() {
        viewModelScope.launch {
            val result = processor.processPayment(BigDecimal("99.99"))
            // Pemrosesan hasil
        }
    }
}

Strategy dengan Hilt/Dagger — dalam proyek Android, strategi sering disuntikkan melalui DI. Hilt menyediakan implementasi konkret PaymentStrategy melalui @Binds atau @Provides. Ini memungkinkan perubahan strategi tanpa mengubah kode konteks — cukup ubah modul DI untuk build yang berbeda (debug/release). Misalnya, untuk debug disuntikkan MockPaymentStrategy, untuk produksi — strategi bank nyata. Kombinasi Strategy + DI memberikan fleksibilitas maksimal.

Perbandingan Strategy dengan State, Command, dan Template Method

Strategy vs State — secara struktural polanya identik: keduanya menggunakan komposisi dengan antarmuka dan kelas konkret. Perbedaannya terletak pada tujuan: Strategy memilih algoritma independen, State mengelola perilaku objek tergantung pada keadaannya. Di State konteks sendiri mengubah strategi saat keadaan berubah, di Strategy konteks tidak mengontrol peralihan — klien secara eksplisit menentukan algoritma. Strategi tidak saling mengetahui, keadaan dapat bertransisi satu sama lain.

Strategy vs Command — Command mengenkapsulasi satu tindakan sebagai objek, Strategy mengenkapsulasi serangkaian algoritma yang dapat dipertukarkan. Command — «apa yang harus dilakukan» (satu panggilan execute), Strategy — «bagaimana melakukannya» (algoritma dari beberapa langkah). Command digunakan untuk antrian, eksekusi tertunda, undo/redo. Strategy — untuk memilih cara menjalankan tugas saat runtime. Perintah dapat diparametrize dengan strategi, menggabungkan kedua pola.

KarakteristikStrategyStateCommandTemplate Method
TujuanAlgoritma yang dapat dipertukarkanPerilaku tergantung keadaanEnkapsulasi permintaanKerangka algoritma
PerubahanEksplisit oleh klienOtomatis oleh konteksOleh klien atau antrianDengan pewarisan
TingkatObjek (komposisi)Objek (komposisi)ObjekKelas (pewarisan)

Strategy vs Template Method — kedua pola mendefinisikan algoritma, tetapi dengan cara berbeda. Template Method menggunakan pewarisan: kelas dasar mendefinisikan kerangka algoritma (metode template), subkelas mengesampingkan langkah-langkah individual. Strategy menggunakan komposisi: algoritma sepenuhnya dipindahkan ke kelas terpisah. Template Method lebih sederhana untuk kasus dengan struktur algoritma tetap, Strategy — ketika algoritma benar-benar berbeda dan dapat berubah secara dinamis.

Contoh nyata penggunaan pola Strategy

Pemrosesan pembayaran — contoh klasik Strategy. Keranjang belanja toko online berisi daftar produk, dan metode pembayaran dipilih oleh pengguna. Setiap metode (kartu, PayPal, Apple Pay, Google Pay, mata uang kripto) — strategi terpisah dengan tanda tangan bersama pay(amount). Konteks PaymentProcessor tidak tahu bagaimana pembayaran dilakukan — ia memanggil metode bersama. Menambahkan metode pembayaran baru tidak memerlukan perubahan kode keranjang.

Validasi data — Strategy diterapkan untuk aturan validasi yang berbeda dari bidang yang sama. EmailValidatorStrategy, PhoneValidatorStrategy, AgeValidatorStrategy mengimplementasikan antarmuka bersama ValidationStrategy dengan metode validate(input). Formulir pendaftaran menggunakan serangkaian strategi untuk memeriksa setiap bidang. Strategi validasi dapat digabungkan dalam rantai (Chain of Responsibility) atau diterapkan sekaligus dalam satu putaran. Ini menggantikan pemeriksaan if-else yang panjang dengan kumpulan validator polimorfik.

swift
// Strategi pengurutan
protocol SortingStrategy {
    func sort<T>(_ items: [T]) -> [T] where T: Comparable
}

struct QuickSortStrategy: SortingStrategy {
    func sort<T>(_ items: [T]) -> [T] { /* quicksort */ items }
}

struct MergeSortStrategy: SortingStrategy {
    func sort<T>(_ items: [T]) -> [T] { /* mergesort */ items }
}

class SortedDataSource<T> {
    private var strategy: SortingStrategy
    func display(_ items: [T]) { let sorted = strategy.sort(items) }
}

Otentikasi — dalam aplikasi seluler, strategi otentikasi berubah tergantung pada penyedia. AuthStrategy dengan metode login(), logout(), getToken() diimplementasikan untuk EmailPasswordAuth, GoogleAuth, AppleAuth, BiometricAuth. Konteks AuthManager menerima strategi melalui DI atau pabrik. Ini memungkinkan penambahan penyedia otentikasi baru tanpa mengubah layar masuk. Pola Strategy — dasar untuk banyak pustaka OAuth dan Firebase Authentication.

Pertanyaan yang Sering Diajukan

Kapan menggunakan Strategy daripada if-else?

Strategy dibenarkan ketika Anda memiliki 3+ algoritma yang dapat berubah atau diperluas. Jika algoritmanya 2 dan stabil — if-else sederhana lebih murah. Gunakan Strategy ketika algoritma digunakan di berbagai bagian aplikasi, ketika perlu mengganti algoritma saat runtime, atau ketika setiap algoritma membutuhkan dependensi dan pengujian sendiri.

Apakah Strategy sama dengan State?

Tidak, ini adalah pola yang berbeda dengan struktur serupa. Strategy — klien secara eksplisit memilih algoritma, dan strategi bersifat independen. State — objek mengubah perilakunya sendiri saat keadaan internal berubah, dan keadaan dapat bertransisi satu sama lain. Di State konteks mengelola perubahan keadaan, di Strategy — kode klien.

Bisakah Strategy digunakan tanpa kelas — melalui closures?

Ya, di Swift dan Kotlin strategi dapat diteruskan sebagai closure atau lambda. Swift: typealias PaymentHandler = (Decimal) async throws -> PaymentResult. Kotlin: typealias PaymentFun = suspend (BigDecimal) -> PaymentResult. Ini menyederhanakan kode untuk kasus sederhana, tetapi penamaan dan dokumentasi hilang. Untuk 1-2 algoritma — closure sudah cukup, untuk 4+ — kelas terpisah lebih baik.

Bagaimana cara menguji pola Strategy?

Setiap strategi diuji dengan pengujian unit terpisah dengan dependensi mock. Konteks diuji dengan strategi mock — diperiksa bahwa konteks memanggil metode strategi dan meneruskan parameter yang benar. Di Swift gunakan XCTest + protokol untuk mock, di Kotlin — MockK atau Mockito. Keuntungan utama: setiap strategi diuji secara terisolasi tanpa konfigurasi yang rumit.

Apakah Strategy adalah pola GoF?

Ya, Strategy (Strategi) — salah satu dari 23 pola yang dijelaskan dalam buku «Design Patterns: Elements of Reusable Object-Oriented Software» (Gamma, Helm, Johnson, Vlissides, 1994). Termasuk dalam kelompok pola perilaku (Behavioral Patterns). Sinonim: Policy (Kebijakan). Kode contoh asli dalam Smalltalk-80 tersedia di edisi asli GoF.

Kesimpulan

  • Strategy — pola perilaku untuk algoritma yang dapat dipertukarkan dengan antarmuka bersama
  • Enkapsulasi — setiap algoritma diisolasi dalam kelas strategi terpisah
  • iOS Swift — implementasi melalui Protocol, struktur, dan closures
  • Android Kotlin — implementasi melalui Interface, lambda, dan DI dengan Hilt
  • Prinsip Open/Closed — strategi baru ditambahkan tanpa mengubah konteks
  • Penerapan — pembayaran, validasi, pengurutan, otentikasi, pemformatan

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga