【问题标题】:Objective-c - Recommended pattern to cascade decision making in a class clusterObjective-c - 在类集群中级联决策的推荐模式
【发布时间】:2015-09-10 16:20:38
【问题描述】:

我想创建一个“多级”类集群,这样每个“具体”类可以在满足某些条件时返回一个更具体的实例。

例如在基类中:

@interface BaseClass : NSObject  // this is the public API of the service

+(instancetype)initWithData:(Data *)data;
// common interface of all the specific implementations..
...
...

@end


@implementation BaseClass

// basically implementing the "cluster"
+(instancetype)initWithData:(Data *)data {
  // testing some conditions to decide on the more specific version of the class to return...
  if (data.condition == condition1) {
     return [[SomeClassOne alloc] initWithData:data];
  }
  if(data.condition == condition2) {
     return [[SomeClassTwo alloc] initWithData:data];
  }
  ... 
  // have many types which could be returned 
}


// an example of a specific instance that should be returned from the cluster - all of these classes are "private" implementations of the base class
@implementation SomeClassOne

-(instancetype)initWithData:(Data *)data {
  self = [super initWithData:data];
  // all was good until a new optimization came about...
  // now this instance can refine the class cluster even better
  // what I would want is a way to do:
  self = [[SomeClassOne_EvenBetterVersion alloc] initWithData:data];
  // but this would be bad - and would cause recursion if the new version inherits this version...
}
@end

我不想在基类中不断添加新条件(大的“if”语句),因为条件变得非常特定于具体类 - 主要是与新功能有关的优化。

有更好的模式吗?

我曾考虑在每个子类中创建一个类方法来进行额外检查 - 但是在每个子类中调用 [Subclass initWithData:data] 变得非常尴尬

【问题讨论】:

    标签: objective-c design-patterns optimization class-cluster


    【解决方案1】:

    一些可能会改善这一点的事情:

    1) 覆盖 allocWithZone:让您的 BaseClass 返回 BaseClass 的单例实例。这可以防止额外的对象分配。然后 BaseClass 的 initWithData: 方法将返回真实的实例。

    2) 以这样一种方式构造或转换 Data 参数,以便于字典查找以获取您的具体实现类。在 initWithData 中实例化它:

    在 +initialize 中静态创建一个结构(或随时动态),如下所示:

    static_dictionary = @{ @"Some string or hashable condition" : [CoolSubclass class],
                           @"Condition2" : [CoolerSubclass class] };
    

    现在在 initWithData 中:您可以不断地查找您的类型和干净的代码。

    Class my_type = [static_dictionary objectForKey: transformated_data_condition];
    if(my_type == Nil) { // throw? return nil? }
    return [[my_type alloc] initWithData: data];
    

    现在重复这个过程变得很容易——也许 CoolerSubclass 是另一个类集群,它有自己的类型字典和测试方法。

    【讨论】:

    • 我认为这些区域已不再使用。关于使用字典 - 这很好,但要级联到下一个级别需要创建一个新的 -init 方法以确保子类不会调用“super”
    • alloc 调用 allocWithZone:,我相信它仍然是这种情况的首选方法。您的子类 init 方法应该是智能的并绕过 initWithData(调用 init)。
    • 此方法存在历史原因; Objective-C 不再使用内存区域。 developer.apple.com/library/mac/documentation/Cocoa/Reference/…:
    • 在 NSObject 中调动它并在它被调用时记录下来。它的原始目的不再相关,但它仍然被称为。这是一个很好的资源:@​​987654322@ 同样来自上面的 NSObject 文档:由于历史原因,alloc 调用 allocWithZone:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 2014-05-17
    • 2016-04-09
    • 1970-01-01
    相关资源
    最近更新 更多