Skip to content

Instantly share code, notes, and snippets.

@vibrazy
Created August 5, 2022 08:08
Show Gist options
  • Save vibrazy/40097f284cc09013b716a093b60de9f1 to your computer and use it in GitHub Desktop.
Save vibrazy/40097f284cc09013b716a093b60de9f1 to your computer and use it in GitHub Desktop.
Strategy Pattern
import UIKit
import Combine
// MADE UP CODE
typealias Package = Int
struct Offerings {
var monthtly: Package?
var annual: Package?
var lifetime: Package?
}
protocol PurchaseStrategy {
init(package: Package?)
func purchase(completion: @escaping (Bool) -> Void)
}
struct MonthlyPurchaseStrategy: PurchaseStrategy {
init(package: Package?) {}
func purchase(completion: @escaping (Bool) -> Void) {
print(#function, "Monthly")
completion(true)
}
}
struct AnnualPurchaseStrategy: PurchaseStrategy {
init(package: Package?) {}
func purchase(completion: @escaping (Bool) -> Void) {
print(#function, "Annual")
completion(true)
}
}
struct LifetimePurchaseStrategy: PurchaseStrategy {
init(package: Package?) {}
func purchase(completion: @escaping (Bool) -> Void) {
print(#function, "Lifetime")
completion(true)
}
}
struct EmptyPackagePurchaseStrategy: PurchaseStrategy {
init(package: Package?) {}
func purchase(completion: @escaping (Bool) -> Void) {
print(#function, "Sad Panda")
completion(false)
}
}
enum PurchaseStrategyFactory {
static func makePackage(offerings: Offerings?) -> PurchaseStrategy {
guard let offerings = offerings else {
return EmptyPackagePurchaseStrategy(package: nil)
}
if let monthly = offerings.monthtly {
return MonthlyPurchaseStrategy(package: monthly)
} else if let annual = offerings.annual {
return AnnualPurchaseStrategy(package: annual)
} else if let lifetime = offerings.lifetime {
return LifetimePurchaseStrategy(package: lifetime)
} else {
return EmptyPackagePurchaseStrategy(package: nil)
}
}
}
class PaywallViewModel: ObservableObject {
var offerings: Offerings?
init(offerings: Offerings?) {
self.offerings = offerings
}
func handleSubscribeButton() {
let purchaseStrategy = PurchaseStrategyFactory.makePackage(
offerings: offerings
)
purchaseStrategy.purchase { [weak self] completed in
print(completed)
}
}
}
// Strategy can be swapped if needed
// Also makes it easier to unit test your strategies.
// This can be also improved by injecting factory etc.
let paywall = PaywallViewModel(offerings: Offerings(monthtly: 20))
paywall.handleSubscribeButton()
paywall.offerings = Offerings(annual: 20)
paywall.handleSubscribeButton()
paywall.offerings = Offerings(lifetime: 20)
paywall.handleSubscribeButton()
paywall.offerings = nil
paywall.handleSubscribeButton()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment