โ† Kembali ke Design Pattern
โ™Ÿ๏ธ
Behavioral

Strategy

Mendefinisikan sekumpulan algoritma yang bisa saling dipertukarkan dan memungkinkan penggantiannya saat runtime.

Masalahnya

Sebuah class punya beberapa varian algoritma yang dipilih lewat if/else atau switch yang besar. Menambah varian baru berarti harus mengubah class itu sendiri.

Cara Kerja

  • โ€บSetiap algoritma dibungkus di balik interface yang sama
  • โ€บAlgoritma bisa diganti saat runtime tanpa mengubah class context
  • โ€บMenghilangkan blok kondisional besar untuk memilih algoritma
  • โ€บContext mendelegasikan pekerjaan ke strategy dan tidak menjalankan algoritmanya sendiri
  • โ€บSangat dekat dengan dependency injection: strategy di-inject dari luar

Kapan Digunakan

โœ“Beberapa algoritma terkait yang hanya berbeda dalam perilakunya
โœ“Perilaku yang bisa ditukar: sorting, kompresi, pembayaran, validasi
โœ“Mengganti rantai if/else panjang yang memilih algoritma
โœ“Saat kamu ingin pengguna bisa mengonfigurasi atau memperluas perilaku

Contoh di Dunia Nyata

๐ŸŽ
iOS

JSONEncoder.dateEncodingStrategy, URLSessionConfiguration, UICollectionViewLayout

๐Ÿค–
Android

RecyclerView.LayoutManager (Linear/Grid/Staggered), Room TypeConverter

๐ŸŒ
Web

Passport.js strategies (local, OAuth), webpack's loader config, sorting comparators

Contoh Kode

Swift
protocol ValidationStrategy {
    func validate(_ input: String) -> Bool
}

struct EmailValidator: ValidationStrategy {
    func validate(_ input: String) -> Bool {
        input.contains("@") && input.contains(".")
    }
}

struct PhoneValidator: ValidationStrategy {
    func validate(_ input: String) -> Bool {
        input.allSatisfy { $0.isNumber } && input.count >= 10
    }
}

struct MinLengthValidator: ValidationStrategy {
    let minLength: Int
    func validate(_ input: String) -> Bool { input.count >= minLength }
}

class InputField {
    var strategy: ValidationStrategy

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

    func isValid(_ input: String) -> Bool { strategy.validate(input) }
}

let emailField = InputField(strategy: EmailValidator())
print(emailField.isValid("agus@example.com"))  // true
print(emailField.isValid("not-an-email"))      // false

emailField.strategy = MinLengthValidator(minLength: 6)
print(emailField.isValid("hello"))             // false