【问题标题】:Are class methods the best way in Objective-C to implement a factory method?类方法是 Objective-C 中实现工厂方法的最佳方式吗?
【发布时间】:2011-09-24 22:06:44
【问题描述】:

似乎我在 Objective C 中看到了很多类方法,例如 +(NSString*)stringWithString:(NSString *)string+(NSArray)arrayWithArray:(NSArray *)array 等。我刚刚开始考虑设计模式,对我来说这些方法看起来像是产生特定实现的小工厂基于提供的参数的字符串或数组(stringWith string,string ByAppendingString)。本质上,这看起来很像 Design Patterns 一书中演示的带有参数的工厂方法。有一个更好的方法吗?我应该创建混合这些类方法和实例方法的接口,还是只创建没有任何实例方法的工厂对象?我很困惑。

【问题讨论】:

    标签: objective-c design-patterns factory factory-pattern


    【解决方案1】:

    虽然Apple claims 这些方法是工厂方法,但我认为它们与设计模式 中的工厂方法模式不同。 DP 工厂方法模式使用抽象的Creator 类,以及生成具体Product 类的具体子类。您描述的方法(通常称为“便利构造函数”)几乎从未以这种方式实现。 Apple 对工厂方法的定义是“一种类方法,为了方便客户,它创建一个类的实例。工厂方法将分配和初始化结合在一个步骤中,并返回一个自动释放的类实例。”这就是为什么我认为“便利构造函数”这个术语比“工厂方法”更合适,也更不容易混淆。

    NSString 是一个class cluster,它与工厂方法模式有一些相似之处,因为您可以从同一个方法调用中接收不同的具体类。但是类簇不同于工厂方法,因为超类知道所有子类,调用者与之交互的是超类。在工厂方法模式中,调用者与 Creator 类的子类进行交互。

    所以对于您的问题:您应该在调用者方便时创建方便的方法。它补充:

    Foo *foo = [[[Foo alloc] initWithSomething:something] autorelease];
    

    Foo *foo = [Foo fooWithSomething:something];
    

    我的经验是,90% 的情况下你不应该这样做。额外的代码不值得。您应该等到看到 initWithSomething: 被称为 lot 之后紧跟一个 autorelease,然后添加一个便利构造函数以使事情更方便。像stringWith... 这样的东西在这个类中。他们被称为很多。

    【讨论】:

    • 我想这就是我的困惑所在,Apple。我一定在某个时候读过那个页面,他们称它们为工厂方法。它们实际上只是自动释放对象的简写。这是有道理的......所以如果我想实现实际的 DP 工厂方法模式,我需要继续创建一个我承诺自己不会实现的常规旧接口......没有抽象在 Obj-C 中指定...?
    • 抽象接口的近似等价物是@protocol。然而,没有办法创建一个半抽象类,就像你可以在编译器强制执行的 C++ 中一样。当我这样做时,我一般只是在抽象方法中调用NSAssert 来说明它是抽象的。
    【解决方案2】:

    根据定义,工厂方法必须是类方法,因为您需要类来生成新实例。 Apple 的框架混合使用工厂方法(例如 arrayWithObjects)和非工厂初始化(initWithObjects)。

    除此之外,我不确定我是否理解您的问题。对于大多数重要的类,您将同时拥有类工厂方法和实例初始化方法。

    【讨论】:

    • 他被设计模式搞糊涂了,这个概念单枪匹马地导致了比我见过的任何其他代码都多的糟糕代码。
    • @DanielRHicks 你是说工厂方法模式导致了很多糟糕的代码?我很少在野外看到实际的工厂方法模式。你是说抽象工厂模式吗?我曾经看到一个有时用得不好。或者你的意思是其他一些不是真正 DP 模式的工厂模式?还是您的意思是“模式”的概念是造成不良代码的原因?
    • 嗯,使用工厂方法没有错。正是设计模式和相关方案(以及它们与“模式”的机械映射)中的“分析”技术导致了不合逻辑的应用程序,其中包含许多不必要的模块和接口,并且缺乏正确的、“干净”的接口。跨度>
    【解决方案3】:

    文档中通常将这些方法描述为便捷方法 - 编写 [NSString stringWithString:s] 比编写 [[[NSString alloc] initWithString:s] autorelease] 更短,但它们的作用相同。

    关于工厂的角度,我觉得你是不是把这些方法当成一种工厂,看你对工厂的具体定义是什么口味的问题。

    【讨论】:

      【解决方案4】:

      Objective-C中的类也是对象(Class Objects),工厂类设计模式是语言的一部分。

      【讨论】:

        猜你喜欢
        • 2012-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多