快速使用具有不同协议的工厂模式

时间:2019-02-02 20:25:54

标签: ios swift generics swift4.2

我试图快速使用工厂模式,请给出我的代码

我有两个协议

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。

我看到其他的例子,但所有这些具有它们符合像矩形相同的协议,正方形和圆形符合相同的协议的形状。

就我而言,我有两个单独的协议,它们执行完全不同的操作,所以在示例中尝试执行的操作甚至可能吗?或者我结束了的方式就是去了解它的唯一途径。

请提出什么是最好的方法。

2 个答案:

答案 0 :(得分:0)

建议快速选择:

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
}

答案 1 :(得分:0)

首先,我非常怀疑“管理器”是值(结构)而不是实例(类)。您真的是真的要在这里使用结构和协议吗?结构没有身份;具有相同属性的两个结构必须彼此完全可互换,并且类似的东西通常不会被命名为“ 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)

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

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

您似乎在这里创建了很多协议,我敢打赌,它们大多数都只有一个实现。那太糟糕了,斯威夫特。在有特定需求之前不要创建协议。不要创造有趣的景点。他们会很快烧死你。

如果您的协议确实看起来像这样,并且您真的对这些方法有不同的实现(即,如果只有MyProtocol1一种实现,则不要这样做” “),您真正想要的是函数:

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

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

这将使您可以根据需要创建不同的API。但同样,仅当您需要这种灵活性时。如果不是这样,则仅将类用于实例,将结构用于值,并避免使用协议,直到程序中至少有2个(最好是3个)实现。

相关问题