gpt4 book ai didi

swift - 在 Swift 中使用 DI 时避免胖初始化器

转载 作者:行者123 更新时间:2023-11-28 07:33:53 26 4
gpt4 key购买 nike

我试图理解 Swift 中的 DI

我知道有 Swinject 等框架可以帮助 DI 但是我很想自己理解这一点,而不是使用太多框架的魔力。

以下面的代码为例

我的 ProfileService 的初始化程序只会随着这个服务的扩展而继续增长并变得越来越胖,并且由于项目包含多个类,所以相同的模式会重复很多次。

如何避免这种情况?我希望找到一种方法来支持轻松维护,同时仍然获得直接和简单代码注入(inject)的所有好处。

我在想也许可以使用 ProtocolStruct 来包含依赖项并将其注入(inject),但是无法理解如何最好地实现它。

import UIKit

class UserService {
func currentUser() -> String {
return "some username"
}
}

class AvatarService {
func currentUserAvatarUrl() -> String {
return "https://foo.bar/image.png"
}
}

class MessageService {
func currentInbox() -> [String:String] {
return [
"9279n1n2283":"something something",
"m2j292i2m2n":"something something something"
]
}
}

class ProfileService {
private let userService: UserService
private let avatarService: AvatarService
private let messageService: MessageService

init(userService: UserService, avatarService: AvatarService, messageService: MessageService) {
self.userService = userService
self.avatarService = avatarService
self.messageService = messageService
}

func getLoggedInUser() -> String {
return userService.currentUser()
}

func getUserAvatar() -> String {
return avatarService.currentUserAvatarUrl()
}

func getInboxMessages() -> [String:String] {
return messageService.currentInbox()
}
}

let userService = UserService()
let avatarService = AvatarService()
let messageService = MessageService()

let profileService = ProfileService(userService: userService, avatarService: avatarService, messageService: messageService)

profileService.getLoggedInUser()
profileService.getUserAvatar()
profileService.getInboxMessages()

最佳答案

我的建议是根本不要直接对这些类进行依赖注入(inject)。我会做这样的事情:

import Foundation

// MARK: Protocols

protocol UserService {
var username: String { get }
}

protocol AvatarService {
var userAvatarURL: URL { get }
}

protocol MessageService {
var inbox: [String: String] { get }
}

protocol GlobalServiceContext {
var userService: UserService { get }
var avatarService: AvatarService { get }
var messageService: MessageService { get }
}

// MARK: Mock Implementations

class MockUserService: UserService {
let username = "test_user"
}

class MockAvatarService: AvatarService {
let userAvatarURL = URL(string: "https://en.wikipedia.org/static/images/project-logos/enwiki.png")!
}

class MockMessageService: MessageService {
let inbox = [
"test subject 1": "test message 1",
"test subject 2": "test message 2",
"test subject 3": "test message 3",
]
}

class MockServiceContext: GlobalServiceContext {
let userService: UserService = MockUserService()
let avatarService: AvatarService = MockAvatarService()
let messageService: MessageService = MockMessageService()
}

// MARK: Mock Implementations

class ProdUserService: UserService {
// TODO: Substitute real implementation here
let username = "prod_user"
}

class ProdAvatarService: AvatarService {
// TODO: Substitute real implementation here
let userAvatarURL = URL(string: "https://en.wikipedia.org/static/images/project-logos/enwiki.png")!
}

class ProdMessageService: MessageService {
let inbox = [ // TODO: Substitute real implementation here
"Prod subject 1": "Prod message 1",
"Prod subject 2": "Prod message 2",
"Prod subject 3": "Prod message 3",
]
}

class ProdServiceContext: GlobalServiceContext {
let userService: UserService = ProdUserService()
let avatarService: AvatarService = ProdAvatarService()
let messageService: MessageService = ProdMessageService()
}

// MARK: Usage

let ServiceContext: GlobalServiceContext = MockServiceContext()

class ProfileService {
var username: String { return ServiceContext.userService.username }
var userAvatarURL: URL { return ServiceContext.avatarService.userAvatarURL }
var inbox: [String:String] { return ServiceContext.messageService.inbox }
}

let profileService = ProfileService()
print(profileService.username)
print(profileService.userAvatarURL)
print(profileService.inbox)

它包含您所有的全局状态(您的 API、服务、数据库等):

  • 成为一个单一的对象
  • 全局可用
  • 其值可以替代模拟实现

关于swift - 在 Swift 中使用 DI 时避免胖初始化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53821836/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com