假设我们有简单的枚举消息类型:
enum MessageType {
case audio
case photo
case text
}
有Handler
类只处理具有特定类型的消息:
class Handler {
let allowed: [MessageType]
init(_ allowed: [MessageType]) { self.allowed = allowed }
func canHandle(_ messageType: MessageType) -> Bool {
return allowed.contains(messageType)
}
}
基本用法示例:
let handler = Handler([.audio, .photo])
print(handler.canHandle(.text)) // Prints false
我想升级MessageType
并为某些消息类型添加相关值。
class Audio {}
enum MessageType {
case audio(Audio)
case photo
case text
}
问题是我无法在allowed
数组中存储枚举模式,以便将来检查canHandle
:
// error: '_' can only appear in a pattern or on the left side of an assignment
let handler = Handler([.audio(_), .photo])
是否有可能以“干净”的方式解决此类案件?
MessageType
,因为它位于第三方库中(例如,使参数可选并传递nil
)MessageType.audio(Audio)
初始化Audio
因为它可能有私有初始化程序switch
case let
,canHandle
或其他硬编码检查
有什么建议吗?感谢
答案 0 :(得分:1)
enum MessageType {
case audio(String)
case photo
case text
}
protocol SneakyEquatableMessage {
func equals(message: MessageType) -> Bool
}
extension MessageType: SneakyEquatableMessage {
func equals(message: MessageType) -> Bool {
switch (self, message) {
case (.audio(_), .audio(_)),
(.photo, .photo),
(.text, .text):
return true
default:
return false
}
}
}
class Handler {
let allowed: [MessageType]
init(_ allowed: [MessageType]) { self.allowed = allowed }
func canHandle(_ messageType: MessageType) -> Bool {
return allowed.contains { $0.equals(message: messageType) }
}
}
基本用法
let handler = Handler([.audio(""), .photo])
print(handler.canHandle(.text)) // Prints false
print(handler.canHandle(.audio("abc")) //Prints true
这个特定的部分在这个上下文中更具体,但最终你会在Swift 4中以某种方式破坏你的枚举。所以这是我的建议:依赖注入 Handler
内的工厂模式的em>。这样就可以非常干净地解决所有问题,而无需在Handler或optionals中触摸开关。
enum DisassembledMessage {
case audio
case photo
case text
}
protocol MessageTypeFactory {
func disassemble(message: MessageType) -> DisassembledMessage
func disassemble(messages: [MessageType]) -> [DisassembledMessage]
}
class Handler {
let allowed: [MessageType]
let factory: MessageTypeFactory
init(allowed: [MessageType], with factory: MessageTypeFactory) {
self.allowed = allowed
self.factory = factory
}
func canHandle(_ messageType: DisassembledMessage) -> Bool {
return factory
.disassemble(messages: allowed)
.contains { $0 == messageType }
}
}
基本用法
let audioValue: Audio = //...
let audioMessage = MessageType.audio(audioValue)
let factory: MessageTypeFactory = //...
let handler = Handler(allowed: [audioMessage, .photo], with: factory)
print(handler.canHandle(.text)) // Prints false
print(handler.canHandle(factory.disassemble(message: audioMessage))) //Prints true
您可能会问:等等......您刚刚创建了另一个枚举(这也只是一个示例,您可以将其转换为该协议中您想要的任何内容)。好吧,我说:你使用的枚举来自图书馆...请参阅我的笔记部分。此外,您现在可以在任何需要的地方使用该工厂将库类型分解为某些内容,包括Handler
内部。您可以轻松扩展协议MessageTypeFactory
以将您的枚举转换为您创建的其他类型(希望行为),并且基本上只需在需要时将您自己与库类型保持距离。我希望这有助于澄清我的目标!我甚至认为你不应该在课堂上存储MessageType
。您应该存储自己的类型,这是MessageType
的某种映射版本,例如DisassembledType
。
我希望这有帮助!
备注强>
一些事情: