swift 中不同协议的工厂模式

Factory pattern with different protocols in swift

我正在尝试在 swift 中使用工厂模式,给出的是我的代码

我有两个协议

protocol MyProtocol1{
    func callLoginAPI()
}

protocol MyProtocol2{
    func callPaymentAPI()
}

我有两个符合这些协议的结构

struct MyManager1: MyProtocol1{
    func callLoginAPI()
    {
        debugPrint("Inisde--MyManager1 and ready to call an Login API")
    }
}

struct MyManager2: MyProtocol2{
    func callPaymentAPI()
    {
        debugPrint("Inisde--MyManager2 and ready to call Payment API")
    }
}

我想使用工厂模式通过传递协议并返回符合该协议的结构的具体对象来创建管理器的实例

示例: ManagerFactory.create(MyProtocol1) --> should give me instance of MyManager1 and doing ManagerFactory.create(MyProtocol2) --> should give me instance of MyManager2

我认为这可能行不通,因为我在运行时要求具体类型,所以我最终做了这样的事情

protocol IManagerFactory{
    func getMyManager1() -> MyProtocol1
    func getMyManager2() -> MyProtocol2
}

struct ManagerFactory: IManagerFactory
{
    func getMyManager1() -> MyProtocol1 {
        return MyManager1()
    }

    func getMyManager2() -> MyProtocol2 {
        return MyManager2()
    }
}

但我很好奇我在示例中尝试做的事情是否可以实现,我使用的是 swift 4.2.

我看过其他示例,但它们都具有相同的协议,它们遵循相同的协议,例如矩形、正方形和圆形遵循相同的协议形状。

在我的例子中,我有两个独立的协议,它们做完全不同的事情,所以我在示例中尝试做的事情是否有可能?或者我最终采用的方式是唯一的解决方法。

请提出最佳方法。

建议快速选项:

protocol Manager {
    // a generic protocol for all managers
}

protocol BadManager: Manager {
    // properties and behaviour of BadManager
    mutating func noBonus()
}

protocol GoodManager: Manager {
    // properties and behaviour of GoodManager
    mutating func bigBonus()
}

protocol ManagerFactory {
    associatedtype Manager
    mutating func createManager() -> Manager
}

struct gm: GoodManager {
    mutating func bigBonus() {
        print("tons of cookies & coffee")
    }
}

struct bm: BadManager {
    mutating func noBonus() {
        print("all fired")
    }
}

enum ManagerCreator<Manager>: ManagerFactory {
    func createManager() -> Manager {
        switch self {
        case .goodManager:
            return gm() as! Manager
        case .badManager:
            return bm() as! Manager
        }
    }
    case goodManager
    case badManager
}

首先,我非常怀疑 "manager" 是一个值(结构)而不是实例(class)。你真的打算在这里使用结构和协议吗?结构没有标识;两个具有相同属性的结构必须完全可以互换,而类似的东西通常不会被命名 "manager."

你描述的肯定是可以写的。这有点没用。写法如下:

struct ManagerFactory {
    static func create(_ type: MyProtocol1.Protocol) -> MyProtocol1 {
        return MyManager1()
    }

    static func create(_ type: MyProtocol2.Protocol) -> MyProtocol2 {
        return MyManager2()
    }
}

let mgr1 = ManagerFactory.create(MyProtocol1.self)
let mgr2 = ManagerFactory.create(MyProtocol2.self)

但这只是使用方法重载替换名称的一种精心设计的方法。

您似乎想要的是单一方法,但它的 return 类型是什么?即使在 C# 中,如果不添加令人讨厌的向下转换,我也不认为这是可写的。 (这是您和 paulw11 在评论中讨论的重点。)这不是 Swift 的限制;这是类型的基本特征。即使在 JavaScript 中,您也需要知道您期望返回什么,否则您将不知道可以调用哪些方法(只是您在头脑和文档中而不是在编译器和代码)。

您似乎在这里创建了很多协议,我敢打赌它们大多只有一个实现。这很糟糕 Swift。除非您有特定需求,否则不要创建协议。不要为了好玩而创造景点。他们很快就会烧死你。

如果您的协议确实看起来像这样,并且您真的 对这些方法有不同的实现(即,如果只有一个实现 [=12=,请不要这样做) ] "just in case"), 你真正想要的是函数:

struct API {
    let login: () -> Void
    let payment: () -> Void
}

let myAPI = API(login: myLoginFunction, payment: myPaymentFunction)

这将允许您在需要时创建不同的 API。但同样,前提是您需要 这种灵活性。如果没有,只需对实例使用 classes,对值使用结构,并在程序中至少有 2 个(最好是 3 个)实现之前避免使用协议。