我具有一个类LoggingManager
和一个协议LoggingHandler
,并且使用单一方法send(LoggingEvent)
。LoggingManager
保留LoggingHandler
的列表。我希望LoggingManager
是允许从LoggingHandler调用send(LoggingEvent)
的only类,并且使用该协议的类应实现send(LoggingEvent)
方法。
我尝试将LoggingHandler
和LoggingManager
放入同一文件,并将send(LoggingEvent)
标记为fileprivate。但是,在协议中是不允许的。
有没有办法使其起作用?
import Foundation
public struct LoggingEvent {
var eventName: String
var eventParams: [String: Any]
public init(_ name: String, _ eventParams: [String: Any]) {
self.eventName = name
self.eventParams = eventParams
}
public init(_ name: String) {
self.eventName = name
eventParams = [String: Any]()
}
mutating public func addParameter(_ eventName: String, _ eventValue: Any) {
self.eventParams[eventName] = eventValue
}
}
public protocol LoggingHandler {
func logEvent(_ event: LoggingEvent) ///<--- Only LoggingManager should call this function, but classes implementing this should override it
}
public class LoggingManager {
private var loggingHandlers: [LoggingHandler]
static let shared = LoggingManager()
private init() {
loggingHandlers = []
}
public func registerLoggingHandler(_ loggingHandler: LoggingHandler) {
loggingHandlers.append(loggingHandler)
}
public func logEvent(_ event: LoggingEvent) {
for handler in loggingHandlers {
handler.logEvent(event)
}
}
}
这不是最漂亮的解决方案,但这是一个主意。在第一个文件中,您可以定义以下类型:
struct LoggingSecurity {
fileprivate init() {}
}
class LoggingManager {
private let handlers: [LoggingHandler]
private let security: LoggingSecurity
init(handlers: [LoggingHandler]) {
self.handlers = handlers
self.security = .init()
}
func broadcast(event: LoggingEvent) {
handlers.forEach { handler in
handler.send(
event: event,
securedBy: security
)
}
}
}
由于LoggingSecurity.init
方法被标记为fileprivate
,所以唯一可以实例化LoggingSecurity
的类是LoggingManager
。
然后您可以在其他文件中定义以下类型:
struct LoggingEvent {
let data: String
}
protocol LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity)
}
class PrintLoggingHandler: LoggingHandler {
func send(event: LoggingEvent, securedBy security: LoggingSecurity) {
print("LOG: \(event.data)")
}
}