title: Objective-c - Recommended pattern to cascade decision making in a class cluster
body: <p>I would like to create a "multi-level" class cluster such that each "concrete" class could return a more specific instance when certain criteria are met.</p>
  
  <p>For instance in the base class:</p>
  
  <pre><code>@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
  </code></pre>
  
  <p>I don't want to constantly add new conditions in the base class (The big "if" statement) because the conditions become very specific to the concrete classes - mostly optimizations that have to do with new capabilities.</p>
  
  <p>Is there a better pattern for this?</p>
  
  <p>I thought about creating a class method in each sub class that would do additional checks - but this becomes really awkward having to call [Subclass initWithData:data] in each subclass</p>