我正在尝试用Swift创建一些代码,这些代码将启用以下功能。有一个类(称之为数据存储)是代码的主接口——这是大多数API用户在大多数时候都要处理的。
这个数据存储类是灵活的。你可以把它和来自文本文件的数据,或者来自蓝牙数据,或者来自WiFi的数据一起使用,等等。我给这些数据提供商打电话。因此,例如,您可以拥有一个BTProvider类,该类将获取蓝牙数据,并在数据到达时将其发送到数据存储。一个数据存储永远不需要从多个数据提供程序获取数据。
哪些设计模式或语言工具可以帮助我实现这一点?
我考虑过使用协议,但感觉有些倒退——协议定义了对象可以响应的方法——但在本例中,这将是数据存储对象——其中只有一个。在我的头脑中,我觉得我想要一个反向协议——我可以保证“这个对象/调用/这些方法在另一个对象上”。然后所有提供程序都可以实现这一点,数据存储可以有一个方法“setProvider:provider of data”,其中数据提供程序是反向协议的名称。
如果我可以从数据存储中对提供商进行投票(然后他们可以实现一个定义“getMostRecentData”等方法的协议),这会容易得多,但由于其性质(从WiFi、蓝牙等异步数据接收),这是不可能的,而且感觉不优雅-尽管如果你有想法,我会向他们开放!
这似乎不是第一次这样做,所以我对它的一般做法很感兴趣,这样我就不必重新发明轮子了。

最佳答案

我可以保证“这个对象/调用/这些方法在另一个对象上”。
似乎你需要的是委托模式
您可以有一个DataStore(Swift是camel case)并且这个类可以实现几个委托协议。例子:

class DataStore {

    // logic of the DataStore

}

你说你的应用程序主要是一个类(theDataStore),所以我猜你有人用它初始化你的提供者。我建议:
// 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
    }
}

您的provider类将实现该方法,并可以选择实现一个新的processData或只使用默认的方法。如果它实现了它,就不需要调用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)
    }
}

09-04 07:07
查看更多