Created
June 5, 2018 00:49
-
-
Save marty-suzuki/43d576e592ddb9200d6661f5a01b4536 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Playground - noun: a place where people can play | |
import Foundation | |
// MARK: - Pub / Sub | |
protocol Subscription { | |
var id: SubscriptionID { get } | |
} | |
struct SubscriptionID: Equatable { | |
private let rawValue = UUID().uuidString | |
static func == (lhs: SubscriptionID, rhs: SubscriptionID) -> Bool { | |
return lhs.rawValue == rhs.rawValue | |
} | |
} | |
enum NotificationService { | |
private struct _Subscription<T>: Subscription { | |
let id = SubscriptionID() | |
let handler: (T) -> () | |
} | |
final class Provider<T> { | |
private var subscriptions: [_Subscription<T>] | |
init() { | |
self.subscriptions = [] | |
} | |
func publish(_ value: T) { | |
subscriptions.forEach { $0.handler(value) } | |
} | |
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription { | |
let subscription = _Subscription(handler: handler) | |
subscriptions.append(subscription) | |
return subscription | |
} | |
func unsubscribe(_ subscription: Subscription) { | |
subscriptions = subscriptions.filter { $0.id != subscription.id } | |
} | |
} | |
} | |
do { | |
let provider = NotificationService.Provider<Int>() | |
let subscripiton = provider.subscribe { | |
print("provider: \($0)") | |
} | |
provider.publish(1) | |
provider.publish(2) | |
provider.unsubscribe(subscripiton) | |
provider.publish(3) | |
} | |
// MARK: - Constant / Variable | |
final class Variable<T> { | |
var value: T { | |
didSet { | |
provider.publish(value) | |
} | |
} | |
private let provider: NotificationService.Provider<T> | |
init(_ value: T, provider: NotificationService.Provider<T> = .init()) { | |
self.value = value | |
self.provider = provider | |
} | |
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription { | |
handler(value) | |
return provider.subscribe(handler) | |
} | |
func unsubscribe(_ subscription: Subscription) { | |
provider.unsubscribe(subscription) | |
} | |
} | |
final class Constant<T> { | |
var value: T { | |
return variable.value | |
} | |
private let variable: Variable<T> | |
init(_ variable: Variable<T>) { | |
self.variable = variable | |
} | |
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription { | |
return variable.subscribe(handler) | |
} | |
func unsubscribe(_ subscription: Subscription) { | |
variable.unsubscribe(subscription) | |
} | |
} | |
do { | |
let variable = Variable<Int>(0) | |
let subscription1 = variable.subscribe { | |
print("variable: \($0)") | |
} | |
variable.value += 1 | |
variable.value += 1 | |
variable.unsubscribe(subscription1) | |
variable.value += 1 | |
print("variable.value: \(variable.value)") | |
let constant = Constant(variable) | |
let subscription2 = constant.subscribe { | |
print("constant: \($0)") | |
} | |
variable.value += 1 | |
variable.value += 1 | |
constant.unsubscribe(subscription2) | |
variable.value += 1 | |
print("constant.value: \(constant.value)") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment