我正在尝试在Swift中创建一些代码,以启用以下功能。有一个类(称为数据存储区)是代码的主要接口-这是大多数用户在大多数时间都会处理的API。
此数据存储区类非常灵活。您可以将其与文本文件,蓝牙数据或通过WiFi传入的数据等结合使用。我将这些数据提供者称为“数据提供者”。因此,例如,您可以拥有一个BTProvider类,该类将获取蓝牙数据,并在数据到达时将其发送到数据存储。一个数据存储区将永远不需要从多个数据提供者那里获取数据。
哪些设计模式或语言工具可以帮助我实现这一目标?
我考虑过使用协议,但感觉很倒-协议定义了对象可以响应的方法-但在这种情况下,它将是数据存储对象-其中只有一个。在我的脑海中,我觉得我想要一个反向协议-在这里我可以保证“此对象/ calls /这些方法在另一个对象上”。然后,所有提供者都可以实现此目的,并且数据存储区可以具有方法“ setProvider:ProviderOfData”,其中数据提供者是反向协议的名称。
如果我可以从数据存储区中轮询提供程序(那么他们可以实现定义诸如“ getMostRecentData”之类的方法的协议,但是由于它的性质(从WiFi,蓝牙等接收异步数据) 。)这是不可能的,不会让您感到优雅-尽管如果您有想法,我会欢迎他们!
这似乎不是第一次完成,所以我对通常的操作方式很感兴趣,因此不必重新发明轮子。
答案 0 :(得分:1)
我可以保证“此对象在另一个对象上调用/这些方法”的东西。
好像您需要的是 Delegate-Pattern
您可以拥有一个DataStore
(Swift是驼峰式的情况),并且此类可以实现几个委托协议。示例:
class DataStore {
// logic of the DataStore
}
您说您的应用主要是一类(DataStore
),所以我猜您是有人从中初始化您的提供商。我建议:
// Provider Factory
extension DataStore {
func makeBluetoothProvider() {
let btProvider = BTProvider()
btProvider.delegate = self
}
// creation of other providers, or you can create them all at once.
}
不是重要的部分,DataStore
是您的提供者的委托,这样,当他们检索数据时,他们可以调用DataStore
。我会有这样的协议:
protocol ProviderDelegate: class {
func provider(_ provider: Provider, didFinishReceiving data: Data)
}
extension DataStore: ProviderDelegate {
func provider(_ provider: Provider, didFinishReceiving data: Data) {
// read data and do something with it...display it, save it, etc.
}
}
Provider
将是所有提供者的通用类,可能带有网络请求或类似的基本数据。一个例子是:
class Provider {
var delegate: ProviderDelegate
var data: Data
}
class BTProvider: Provider {
// logic only for bluetooth provider
}
根据提供者的行为方式,您可以为每个提供者都有一个委托协议,并可以扩展DataStore
来实现每个协议。仅当行为彼此之间有太大差异时,我才认为。
更新地址注释:协议可以提供代码
一个协议可以提供代码,让我给你看一个例子:
protocol Provider {
weak var delegate: ProviderDelegate { get set }
func fetchData(with url: URL)
func processData(data: Data)
}
extension Provider {
func processData(data: Data) {
// do some processing that all providers have to do equally
// probably also call delegate to tell DataStore it is ready
}
}
您的提供程序类将实现该方法,并且可以选择实现新的processData
或仅使用 default 。如果实现了它,则无需调用override
,您将再也无法访问protocol方法。您的提供者可能如下所示:
class BTProvider: Provider {
weak var delegate: Provider?
func fetchData(with url: URL) {
// do some logic to fetch data for this provider
processData(data: whateverWasFetched)
}
}