简体   繁体   English

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

[英]Factory pattern with different protocols in swift

I am trying to use factory pattern in swift, and give is my code 我正在尝试快速使用工厂模式,请给出我的代码

I have two protocols 我有两个协议

protocol MyProtocol1{
    func callLoginAPI()
}

protocol MyProtocol2{
    func callPaymentAPI()
}

I have two structures which conform to these protocols 我有两个符合这些协议的结构

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")
    }
}

I want to use the factory pattern to create the instance of Manager by passing the Protocol and returning a concrete object of the struct that conforms to that protocol 我想使用工厂模式通过传递协议并返回符合该协议的结构的具体对象来创建Manager的实例

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

I assume that this may not work as I am asking for a concrete type at runtime, so I ended up doing something like this 我认为这可能不起作用,因为我在运行时要求使用具体类型,所以我最终做了这样的事情

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

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

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

But I am curious if what I am trying to do in the example is achievable, I am using swift 4.2. 但是我很好奇在示例中我想做的事,我正在使用Swift 4.2。

I have seen other examples but all of them have the same protocol which they conform to like rectangle, square and circle conform to same protocol shape. 我看到了其他示例,但是它们都具有相同的协议,它们遵循的协议如矩形,正方形和圆形都遵循相同的协议形状。

In my case, I have two separate protocols which do completely different things so is that even possible what I am trying to do in the example? 就我而言,我有两个单独的协议,它们执行完全不同的操作,所以在示例中我可能尝试做的事情甚至可能吗? OR the way I ended up with is the only way to go about it. 否则我最终的方法是唯一的解决方法。

Please suggest what is the best possible approach. 请提出什么是最好的方法。

Suggest a swifty option: 建议一个快速的选择:

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
}

First, I'm very suspicious of a "manager" that is a value (a struct) rather than an instance (a class). 首先,我非常怀疑“管理器”是值(结构)而不是实例(类)。 Do you really mean to be using structs and protocols here at all? 您真的是真的要在这里使用结构和协议吗? Structs have no identity; 结构没有身份; two structs with the same properties must be completely interchangeable for each other, and things like that don't usually get named "manager." 具有相同属性的两个结构必须彼此完全可互换,并且类似的事情通常不会被命名为“ manager”。

What you're describing is certainly writeable. 您所描述的内容肯定是可写的。 It's just kind of useless. 只是没有用。 Here's how you write it: 编写方法如下:

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)

But this is just an elaborate way to use method overloading to replace names. 但这只是使用方法重载替换名称的一种精心设计的方法。

What you seem to want is a single method, but what would its return type be? 您似乎想要的是一个单一方法,但是其返回类型是什么? Even in C#, I don't think this is writable without adding nasty downcasts. 即使在C#中,如果不添加令人讨厌的垂头丧气,我也不认为这是可写的。 (This is the point you and paulw11 discuss in the comments.) This isn't a limitation of Swift; (这是您和paulw11在评论中讨论的重点。)这不是Swift的局限;它只是对Swift的限制。 it's a fundamental characteristic of types. 这是类型的基本特征。 Even in JavaScript, you'd need to know what you expect to get back or else you won't know what methods you can call on it (it's just you track that expectation in your head and docs rather than in the compiler and code). 即使在JavaScript中,您也需要知道期望返回的内容,否则您将不知道可以调用哪种方法(只是在您的头脑和文档中而不是在编译器和代码中跟踪期望) 。

You seem to have created a lot of protocols here, and I'm betting they mostly have exactly one implementation. 您似乎在这里创建了很多协议,我敢打赌,它们大多数都只有一个实现。 That's bad Swift. 那太糟糕了,斯威夫特。 Don't create protocols until you have a specific need for one. 在有特定需求之前不要创建协议。 Don't create attractions for fun. 不要创造有趣的景点。 They will burn you very quickly. 他们会很快烧死你。

If your protocols really look like this, and you really have different implementations of these methods (ie don't do this if there is only one implementation of MyProtocol1 "just in case"), what you really want are functions: 如果您的协议确实看起来像这样,并且您对这些方法确实有不同的实现(即,如果只有MyProtocol1一种实现“以防万一”, MyProtocol1 ),那么您真正想要的是函数:

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

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

This will let you create different APIs if you need them. 如果需要,这将使您创建不同的API。 But again, only if you need this flexibility. 但是同样,仅当您需要这种灵活性时。 If not, just use classes for instances, and structs for values, and avoid protocols until you have at least 2, and better 3, implementations in your program. 如果不是这样,则仅将类用于实例,将结构用于值,并避免使用协议,直到程序中至少有2个(最好是3个)实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM