Strategy — bu nədir, iOS və Android-də strategiya nümunəsi

Müəllif: IT Sectr Dərc olunub: 2026-02-18 Oxuma vaxtı: 9 dəq

Strategy (Strategiya) — bir-birini əvəz edən alqoritmlər ailəsini təyin edən və hər birini ayrıca sinfə (Strategy) yerləşdirən davranış dizayn nümunəsidir. Nümunə alqoritmi anında seçməyə imkan verir: müştəri kodu ümumi Strategy interfeysi vasitəsilə işləyir, konkret tətbiq isə icra zamanı əlavə olunur. iOS-da nümunə Protocol + strategiya sinifləri vasitəsilə, Android-də isə Interface + tətbiqlər vasitəsilə reallaşdırılır. Strategy — 23 GoF nümunəsindən biri, ödənişlərin işlənməsi, valyudasiya, çeşidləmə və məlumatların filtrasiyası üçün geniş tətbiq olunur. Ətraflı — GoF orijinal təsvirində.

Əsas

  • Strategy — bir-birini əvəz edən alqoritmlər ailəsi üçün GoF davranış nümunəsi
  • Alqoritmlərin inkapsulyasiyası — hər alqoritm öz sinfində təcrid olunub
  • Strategy interfeysi — bütün konkret strategiyaların tətbiq etdiyi ümumi müqavilə
  • Varislik əvəzinə kompozisiya — kontekst strategiyaya istinad saxlayır, davranışı miras almır
  • Open/Closed Prinsipi — yeni strategiyalar mövcud kodu dəyişmədən əlavə edilir

Strategy nümunəsi nədir: mahiyyəti və strukturu

Strategy — 23 GoF (Gang of Four) nümunəsindən biri, «Design Patterns: Elements of Reusable Object-Oriented Software» (1994) kitabında təsvir edilmişdir. Nümunə icra zamanı alqoritm seçimi problemini həll edir. Çoxsaylı şərt operatorları (if-else, switch) olan bir sinif yazmaq əvəzinə, Strategy hər alqoritmin ümumi interfeyslə ayrıca sinfə ayrılmasını təklif edir. Kontekst (strategiyadan istifadə edən sinif) Strategy interfeysinə istinad saxlayır və icranı konkret strategiyaya həvalə edir.

Nümunənin strukturu üç elementi əhatə edir: Context (kontekst) Strategy-ə istinad saxlayır və onun metodunu çağırır; Strategy (interfeys) bütün alqoritmlər üçün ümumi metodu bəyan edir; ConcreteStrategy (konkret strategiya) interfeysi tətbiq edir və konkret alqoritmi ehtiva edir. Müştəri lazım olan strategiyanı yaradır və onu konstruktor, setter və ya metod parametri vasitəsilə kontekstə ötürür. Kontekst hansı strategiyanın icra edildiyini bilmir — yalnız interfeyslə işləyir.

KomponentRolNümunə
ContextStrategy-ə istinad saxlayırPaymentProcessor, Sorter
StrategyAlqoritmlər üçün ümumi interfeysProtocol PaymentStrategy
ConcreteStrategyAlqoritmin konkret tətbiqiCardPayment, PayPalPayment

Open/Closed prinsipi — Strategy-nin əsas üstünlüyü. Sistem genişləndirməyə açıqdır (yeni strategiya əlavə etmək olar) və dəyişikliyə qapalıdır (kontekst kodunu dəyişmək lazım deyil). Nümunəsiz yeni alqoritmin əlavə edilməsi mövcud sinfin dəyişdirilməsini tələb edir, bu da OCP-ni pozur və reqressiv səhvlər riskini artırır. Strategy həmçinin siniflərin ölçüsünü azaldır: 200 sətirlik switch-case sinfi əvəzinə hər biri 20 sətir olan 6 sinif alınır.

iOS-da Strategy: Swift ilə Protocol vasitəsilə tətbiqi

Swift-də Strategy Protocol (strategiya interfeysi) və sinif və ya struktur-strategiyalar vasitəsilə tətbiq edilir. Swift protokolları associated types və generic constraints dəstəkləyir, bu da strategiyaların layihələndirilməsində çeviklik verir. Kontekst adətən ViewModel sinfi və ya strategiyanı init və ya xassə vasitəsilə qəbul edən xidmətdir. Nümunə iOS layihələrində hadisələrin işlənməsi, animasiyalar, məlumatların formatlaşdırılması və UI strategiyaları üçün geniş istifadə olunur.

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

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

    func pay(amount: Decimal) async throws -> PaymentResult {
        // Bank API-sinə sorğu göndərilməsi
        return PaymentResult(status: .success, transactionId: "tx_\(UUID())")
    }
}

struct PayPalPaymentStrategy: PaymentStrategy {
    let email: String

    func pay(amount: Decimal) async throws -> PaymentResult {
        // PayPal SDK-ya yönləndirmə
        return PaymentResult(status: .success, transactionId: "pp_\(UUID())")
    }
}

// 3. Kontekst
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)
    }
}

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

SwiftUI-də Strategy — nümunə MVVM ilə təbii şəkildə inteqrasiya olunur. ViewModel strategiya xassəsini ehtiva edir və istifadəçi hərəkəti zamanı onun metodunu çağırır. SwiftUI View @Published və ya @State vasitəsilə məlumat alır — strategiya tətbiq detallarını View-dən gizlədir. Məsələn, mətn validasiyası strategiyası (emailValidator, phoneValidator) giriş sahəsinin növündən asılı olaraq dəyişdirilir. Strategy-nin SwiftUI ilə birləşməsi UIKit-dən varislik olmadan çeviklik verir.

Android-də Strategy: Kotlin ilə Interface vasitəsilə tətbiqi

Kotlin-də Strategy dil səviyyəsində Interface və sadələşdirmə üçün funksional interfeyslərdən (SAM) istifadə edir. Kotlin lambdaları dəstəkləyir ki, bu da ayrıca strategiya sinfi elan etmədən alqoritmləri funksiya kimi ötürməyə imkan verir. Android-də nümunə ViewModel və Use Cases-də məlumat yükləmə, keşləmə və xəta idarəetmə alqoritmlərinin təcrid edilməsi üçün tətbiq olunur. Clean Architecture ilə Android layihələri bayraqlardan (mock, real, cache) asılı olaraq repozitoriyanın müxtəlif tətbiqlərini inyeksiya etmək üçün Strategy-dən istifadə edir.

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

// 2. Konkret strategiyalar
class CardPaymentStrategy(
    private val cardNumber: String,
    private val cvv: String
) : PaymentStrategy {
    override suspend fun pay(amount: BigDecimal): PaymentResult {
        // Retrofit vasitəsilə Bank API
        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. Kontekst
class PaymentProcessor(
    private val strategy: PaymentStrategy
) {
    fun setStrategy(strategy: PaymentStrategy): PaymentProcessor {
        return PaymentProcessor(strategy)
    }

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

// ViewModel-də istifadə
class CheckoutViewModel : ViewModel() {
    private var processor = PaymentProcessor(CardPaymentStrategy("4111...", "123"))

    fun payWithCard() {
        viewModelScope.launch {
            val result = processor.processPayment(BigDecimal("99.99"))
            // Nəticənin işlənməsi
        }
    }
}

Hilt/Dagger ilə Strategy — Android layihələrində strategiyalar tez-tez DI vasitəsilə inyeksiya edilir. Hilt @Binds və ya @Provides vasitəsilə PaymentStrategy-nin konkret tətbiqini təmin edir. Bu, kontekst kodunu dəyişmədən strategiyanı dəyişməyə imkan verir — müxtəlif kompilyasiya (debug/release) üçün DI modulunu dəyişmək kifayətdir. Məsələn, debug üçün MockPaymentStrategy, release üçün real bank strategiyası inyeksiya edilir. Strategy + DI birləşməsi maksimal çeviklik verir.

Strategy-nin State, Command və Template Method ilə müqayisəsi

Strategy vs State — struktur olaraq nümunələr eynidir: hər ikisi interfeys və konkret siniflərlə kompozisiyadan istifadə edir. Fərq məqsəddədir: Strategy müstəqil alqoritm seçir, State obyektin vəziyyətindən asılı olaraq davranışını idarə edir. State-də kontekst vəziyyət dəyişdikdə strategiyanı özü dəyişir, Strategy-də kontekst keçidi idarə etmir — müştəri alqoritmi açıq şəkildə təyin edir. Strategiyalar bir-biri haqqında bilmir, vəziyyətlər isə bir-birinə keçə bilər.

Strategy vs Command — Command tək bir hərəkəti obyekt kimi inkapsulyasiya edir, Strategy bir-birini əvəz edən alqoritmlər dəstini inkapsulyasiya edir. Command — «nə etməli» (bir execute çağırışı), Strategy — «necə etməli» (bir neçə addımdan ibarət alqoritm). Command növbələr, gecikmiş icra, undo/redo üçün istifadə olunur. Strategy — icra zamanı tapşırığın yerinə yetirilmə üsulunu seçmək üçün. Komandalar strategiyalarla parametrləşdirilərək hər iki nümunəni birləşdirə bilər.

XarakteristikaStrategyStateCommandTemplate Method
MəqsədBir-birini əvəz edən alqoritmlərVəziyyətdən asılı davranışSorğunun inkapsulyasiyasıAlqoritm skeleti
DəyişməMüştəri tərəfindən açıqKontekst tərəfindən avtomatikMüştəri və ya növbə iləVarisliklə
SəviyyəObyekt (kompozisiya)Obyekt (kompozisiya)ObyektSinif (varislik)

Strategy vs Template Method — hər iki nümunə alqoritmləri təyin edir, lakin fərqli üsullarla. Template Method varislikdən istifadə edir: əsas sinif alqoritmin skeletini (şablon metodu) təyin edir, alt siniflər ayrı-ayrı addımları dəyişdirir. Strategy kompozisiyadan istifadə edir: alqoritm tamamilə ayrıca sinfə çıxarılıb. Template Method sabit alqoritm strukturu olan hallar üçün daha sadədir, Strategy — alqoritmlər tamamilə fərqli olduqda və dinamik dəyişə bildikdə.

Strategy nümunəsinin real istifadə nümunələri

Ödənişlərin işlənməsi — Strategy-nin klassik nümunəsi. İnternet mağazasının səbəti məhsul siyahısını ehtiva edir, ödəniş üsulu isə istifadəçi tərəfindən seçilir. Hər üsul (kart, PayPal, Apple Pay, Google Pay, kriptovalyuta) — pay(amount) ümumi imzası olan ayrıca strategiyadır. PaymentProcessor konteksti ödənişin necə aparıldığını bilmir — ümumi metodu çağırır. Yeni ödəniş üsulunun əlavə edilməsi səbət kodunun dəyişdirilməsini tələb etmir.

Məlumatların validasiyası — Strategy eyni sahənin müxtəlif validasiya qaydaları üçün tətbiq olunur. EmailValidatorStrategy, PhoneValidatorStrategy, AgeValidatorStrategy validate(input) metodu ilə ümumi ValidationStrategy interfeysini tətbiq edir. Qeydiyyat forması hər sahəni yoxlamaq üçün strategiyalar dəstindən istifadə edir. Validasiya strategiyaları zəncirlə (Chain of Responsibility) birləşdirilə və ya dövrədə hamısı birdən tətbiq edilə bilər. Bu, uzun if-else yoxlamalarını polimorfik validatorlar kolleksiyası ilə əvəz edir.

swift
// Çeşidləmə strategiyası
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) }
}

Autentifikasiya — mobil tətbiqlərdə autentifikasiya strategiyaları provayderdən asılı olaraq dəyişir. login(), logout(), getToken() metodları ilə AuthStrategy EmailPasswordAuth, GoogleAuth, AppleAuth, BiometricAuth üçün tətbiq edilir. AuthManager konteksti strategiyanı DI və ya fabrik vasitəsilə qəbul edir. Bu, giriş ekranını dəyişmədən yeni autentifikasiya provayderləri əlavə etməyə imkan verir. Strategy nümunəsi bir çox OAuth kitabxanaları və Firebase Authentication üçün əsasdır.

Tez-tez verilən suallar

Strategy nə vaxt if-else əvəzinə istifadə edilməlidir?

Strategy 3+ alqoritm olduqda və onlar dəyişə və ya genişlənə bildikdə əsaslandırılır. Əgər 2 alqoritm varsa və onlar sabitdirsə — sadə if-else daha az xərclidir. Strategy-dən alqoritmlər tətbiqin müxtəlif hissələrində istifadə edildikdə, alqoritmləri icra zamanı dəyişmək lazım olduqda və ya hər alqoritm öz asılılıqları və testləri tələb etdikdə istifadə edin.

Strategy ilə State eyni şeydirmi?

Xeyr, bunlar oxşar strukturlu fərqli nümunələrdir. Strategy — müştəri alqoritmi açıq seçir və strategiyalar müstəqildir. State — obyekt daxili vəziyyət dəyişdikdə öz davranışını dəyişir və vəziyyətlər bir-birinə keçə bilər. State-də kontekst vəziyyət dəyişməsini idarə edir, Strategy-də — müştəri kodu.

Strategy-ni siniflər olmadan — closures vasitəsilə istifadə etmək olarmı?

Bəli, Swift və Kotlin-də strategiyanı closure və ya lambda kimi ötürmək olar. Swift: typealias PaymentHandler = (Decimal) async throws -> PaymentResult. Kotlin: typealias PaymentFun = suspend (BigDecimal) -> PaymentResult. Bu, sadə hallar üçün kodu sadələşdirir, lakin adlandırma və sənədləşmə itir. 1-2 alqoritm üçün closure kifayətdir, 4+ üçün — ayrıca siniflər daha yaxşıdır.

Strategy nümunəsini necə test etməli?

Hər strategiya mock-asılılıqları ilə ayrıca vahid testlə test edilir. Kontekst mock-strategiya ilə test edilir — kontekstin strategiya metodunu çağırdığı və düzgün parametrləri ötürdüyü yoxlanılır. Swift-də XCTest + protokollar, Kotlin-də MockK və ya Mockito istifadə edin. Əsas üstünlük: hər strategiya mürəkkəb konfiqurasiya olmadan təcrid olunmuş şəkildə test edilir.

Strategy GoF nümunəsidirmi?

Bəli, Strategy (Strategiya) — «Design Patterns: Elements of Reusable Object-Oriented Software» (Gamma, Helm, Johnson, Vlissides, 1994) kitabında təsvir edilmiş 23 nümunədən biridir. Davranış nümunələri qrupuna (Behavioral Patterns) aiddir. Sinonimlər: Policy (Siyasət). Smalltalk-80-də orijinal nümunə kodu GoF-un orijinal nəşrində mövcuddur.

Nəticə

  • Strategy — ümumi interfeyslə bir-birini əvəz edən alqoritmlər üçün davranış nümunəsi
  • İnkapsulyasiya — hər alqoritm ayrıca strategiya sinfində təcrid olunub
  • iOS Swift — Protocol, strukturlar və closures vasitəsilə tətbiq
  • Android Kotlin — Interface, lambdalar və Hilt ilə DI vasitəsilə tətbiq
  • Open/Closed Prinsipi — yeni strategiyalar konteksti dəyişmədən əlavə edilir
  • Tətbiq — ödənişlər, validasiya, çeşidləmə, autentifikasiya, formatlaşdırma

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun