假设我们有简单的枚举消息类型:
enum MessageType {
case audio
case photo
case text
}
Run Code Online (Sandbox Code Playgroud)
有一个Handler类只处理具有特定类型的消息:
class Handler {
let allowed: [MessageType]
init(_ allowed: [MessageType]) { self.allowed = allowed }
func canHandle(_ messageType: MessageType) -> Bool {
return allowed.contains(messageType)
}
}
Run Code Online (Sandbox Code Playgroud)
基本用法示例:
let handler = Handler([.audio, .photo])
print(handler.canHandle(.text)) // Prints false
Run Code Online (Sandbox Code Playgroud)
我想升级我的MessageType并为某些消息类型添加相关值.
class Audio {}
enum MessageType {
case audio(Audio)
case photo
case text
}
Run Code Online (Sandbox Code Playgroud)
问题是我无法将枚举的模式存储在allowed数组中以供将来检入canHandle:
// error: '_' can only appear in a pattern or on the left side of an assignment
let handler = Handler([.audio(_), .photo])
Run Code Online (Sandbox Code Playgroud)
是否有可能以"干净"的方式解决这种情况?
MessageType因为它在第三方库中(例如使参数可选并传递nil)MessageType.audio(Audio)使用伪Audio启动switch,case let或其他硬编码在检查canHandle有什么建议?谢谢
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) }
}
}
Run Code Online (Sandbox Code Playgroud)
基本用法
let handler = Handler([.audio(""), .photo])
print(handler.canHandle(.text)) // Prints false
print(handler.canHandle(.audio("abc")) //Prints true
Run Code Online (Sandbox Code Playgroud)
这个特定的部分在这种情况下更加具体,但最终你将在 Swift 4 中以某种方式分解你的枚举。所以这是我的建议:依赖注入工厂模式内部Handler。这非常干净地解决了您的所有问题,而无需触摸处理程序或选项中的开关。
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 }
}
}
Run Code Online (Sandbox Code Playgroud)
基本用法
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
Run Code Online (Sandbox Code Playgroud)
您可能会问:等等...您刚刚创建了另一个枚举(这也只是一个示例,您可以将其转换为该协议中您想要的任何内容)。好吧,我说:您正在使用的枚举来自图书馆......请参阅我的注释部分。此外,您现在可以在任何需要将库类型分解为某种内容的地方使用该工厂,包括内部Handler. 您可以轻松扩展协议 MessageTypeFactory以将枚举转换为您创建的其他类型(希望是行为),并且基本上只需在需要时远离库类型即可。我希望这有助于澄清我的意思!我什至认为你不应该存储MessageType在你的班级中。您应该存储自己的类型,它是 的某种映射版本MessageType,例如DisassembledType.
我希望这有帮助!
笔记
一些东西:
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |