Created
June 24, 2016 06:21
-
-
Save ajonno/3d71af7402da7c8b239eea6982c96b9d to your computer and use it in GitHub Desktop.
Example of Repository pattern using Swift
This file contains hidden or 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
// credit -> http://acqui-hire.me/dependency-injection-with-the-cake-pattern-in-swift/ | |
public struct User { | |
public let username: String | |
public let password: String | |
} | |
public protocol UserRepository { | |
func findByUsername(username: String) -> User? | |
} | |
public protocol UserRepositoryComponent { | |
static var userRepository: UserRepository { get } | |
static func createUserRepository() -> UserRepository | |
} | |
public protocol UserService { | |
func authenticate(username: String, password: String) -> User? | |
} | |
public protocol UserServiceComponent { | |
static var userService: UserService { get } | |
static func createUserService() -> UserService | |
} | |
private struct StaticUserRepository: UserRepository { | |
private static let users = [ | |
"admin": User(username: "admin", password: "admin"), | |
"alice": User(username: "alice", password: "123") | |
] | |
private func findByUsername(username: String) -> User? { | |
return StaticUserRepository.users[username] | |
} | |
} | |
public protocol StaticUserRepositoryComponent: UserRepositoryComponent {} | |
extension StaticUserRepositoryComponent { | |
public static func createUserRepository() -> UserRepository { | |
return StaticUserRepository() | |
} | |
} | |
private struct DefaultUserService: UserService { | |
private let userRepository: UserRepository | |
private init(userRepository: UserRepository) { | |
self.userRepository = userRepository | |
} | |
private func authenticate(username: String, password: String) -> User? { | |
guard let user = userRepository.findByUsername(username) else { | |
print("No user found with username: \(username)") | |
return nil | |
} | |
guard user.password == password else { | |
print("Username and password do not match for username: \(username)") | |
return nil | |
} | |
return user | |
} | |
} | |
public protocol DefaultUserServiceComponent: UserServiceComponent {} | |
extension DefaultUserServiceComponent where Self: UserRepositoryComponent { | |
public static func createUserService() -> UserService { | |
return DefaultUserService(userRepository: userRepository) | |
} | |
} | |
public enum AppContext: StaticUserRepositoryComponent, DefaultUserServiceComponent { | |
public static let userRepository = AppContext.createUserRepository() | |
public static let userService = AppContext.createUserService() | |
} | |
// THIS // | |
if let user = AppContext.userService.authenticate("alice", password: "123") { | |
print("Thank you for logging in, \(user.username)!") | |
} else { | |
print("Please check your username and password") | |
} | |
// OR // | |
public typealias ContextType = protocol<UserRepositoryComponent, UserServiceComponent> | |
public struct Context { | |
private let type: ContextType.Type | |
public var userRepository: UserRepository { | |
return type.userRepository | |
} | |
public var userService: UserService { | |
return type.userService | |
} | |
public init(type: ContextType.Type) { | |
self.type = type | |
} | |
} | |
let context = Context(type: AppContext.self) | |
if let user = context.userService.authenticate("alice", password: "123") { | |
print("Thank you for logging in, \(user.username)!") | |
} else { | |
print("Please check your username and password") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment