正确的客户端-服务器框架架构方法(不同的服务器版本)

Correct client-server framework architecture approach (different server versions)

我正在尝试设计和实现一个与服务器通信的框架(这是一个用 Swift 编写的 iOS 框架)。我面临的挑战是架构——有两种与服务器通信的方式,我必须实现这两种方式(不同版本)。我真的很想实现拥有一个无状态客户端,方法如下:Client.authenticate()Client.downloadFile()。问题是当有两个实现时,我最终会在我的客户端 class 中使用这样的方法:

public class func authenticate(state: state) {
    if (state.type == 1) {
        Client1.authenticate(state)
    } else {
        Client2.authenticate(state)
    }
}

对每个方法重复...

我最初想保持这样的客户端 - 无状态和静态并且只有状态对象保存实际状态,因为可能有许多连接到具有各种状态的服务器。通过这种方式,我想避免将客户端作为一个对象,同时保持状态并执行对服务器的调用。问题是这种方法只是……我猜很脏。什么是更 DRY、可读和可持续的方式来做到这一点?

如果没有更多代码示例,我无法完全理解您的意图,但我将向您展示的模式肯定会为您解决问题。

如果您的客户端 class 总是使用 Client1Client2(或者更具体地说,如果您的每个客户端对象 state 变量在其实例中不发生变化lifetime) 你应该使用 Dependency Injection.

您创建了一个 procol(让我们用 authenticate 方法(以及服务器客户端应实现的所有其他方法)将其称为 RemoteClient 并使 Client1Client2 遵守该协议。

现在让您的客户端 class 在其构造函数中接受 RemoteClient

现在无论创建 Client 对象,它都可以决定将什么 注入 到构造函数中:Client1 具体 class 对象,或 Client2.

关于Dependency Injection的文章很多,所以我不会详细介绍。

Example article

您还可以使用策略设计模式,它非常相似但意图有点不同:

Strategy design pattern

Difference between DI and Strategy

编辑

在您在下面的评论中阐明您想要做什么之后:

在这种情况下,您可以使用 reflection/metadata 并使用 dictionary/map 来调用您想要的客户端。

(伪代码)

enum ServerType 
{ 
   client1,
   client2
}

 Dictionary* serversDictionary; // key = ServerType , value = object of protocol type RemoteLocation

static init
 {
    serversDictionary[client1] = Client1.self; // using swift class metadata
    serversDictionary[client2] = Client2.self; // using swift class metadata  
  }

static authenticate(ServerType type) {

 let locationToSendAuthTo = serversDictionary[type]; 
 locationToSendAuthTo.authenticate(type);
}

我不确定 Swift 是否这样工作,因为我才刚刚开始使用它。我不确定您是否可以在 class 类型上调用静态方法。文档对此非常薄弱。

更多信息在这里: Swift class introspection & generics