html5中文学习网

您的位置: 首页 > ios » 正文

iOS开发:八次尝试 带你走进精益编程_IOS开发

[ ] 已经帮助:人解决问题

   开场yaWHTML5中文学习网 - HTML5先行者学习网

  今天, 我们将从一个小功能开始, 先去不假思索的实现它yaWHTML5中文学习网 - HTML5先行者学习网

  Product Repository: Filtering OperationyaWHTML5中文学习网 - HTML5先行者学习网

  Code startyaWHTML5中文学习网 - HTML5先行者学习网

  有一个产品库, 我们要对它做过滤操作.yaWHTML5中文学习网 - HTML5先行者学习网

  第一个需求并不复杂.yaWHTML5中文学习网 - HTML5先行者学习网

  需求1:在仓库中查找所有颜色为红色的产品yaWHTML5中文学习网 - HTML5先行者学习网

  First Attempt: Hard CodeyaWHTML5中文学习网 - HTML5先行者学习网

  我们先用最简单的方式去实现它, 硬编码yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findAllRedProducts:(NSArray *)productsyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (product.color == RED) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  如果这个世界是永恒静止的,这样的实现无可厚非,但世界往往并非如此。yaWHTML5中文学习网 - HTML5先行者学习网

  紧接着,第二个需求来了yaWHTML5中文学习网 - HTML5先行者学习网

  需求2:在仓库中查找所有颜色为绿色的产品yaWHTML5中文学习网 - HTML5先行者学习网

  Second Attempt: ParameterizingyaWHTML5中文学习网 - HTML5先行者学习网

  Copy-Paste是大部分程序员最容易犯的毛病,为此引入了大量的重复代码。yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findAllGreenProducts:(NSArray *)productsyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (product.color == GREEN) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  为了消灭硬编码,得到可重用的代码,可以引入简单的参数化设计。yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findProducts:(NSArray *)products byColor:(ProductColor)coloryaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (product.color == color) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  终于可以放心了, 这个时候我们的产品经理怎么可能让你舒服呢,需求3又来了yaWHTML5中文学习网 - HTML5先行者学习网

  需求3:查找所有重量小于10的所有产品yaWHTML5中文学习网 - HTML5先行者学习网

  Third Attempt: Parameterizing with Every Attribute You Can Think OfyaWHTML5中文学习网 - HTML5先行者学习网

  大部分程序员依然会使用Copy-Paste解决这个问题,拒绝Copy-Paste的陋习,最具实效的一个反馈就是让这个快捷键失效,从而在每次尝试Copy-Paste时提醒自己做更好的设计yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findProducts:(NSArray *)products byWeith:(float)weightyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (product.weight < weight) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  为了消除两者重复的代码,通过简单的参数化往往不能完美解决这类问题,相反地会引入过度的复杂度和偶发成本。yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findProducts:(NSArray *)products byColor:(ProductColor)color byWeith:(float)weight type:(int)typeyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if ((type == 1) && product.color == color) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  continue;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  else if ((type == 2) && (product.weight < weight))yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  continue;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  日常工作中,这样的实现手法非常普遍,函数的参数列表随着需求增加不断增加,函数逻辑承担的职责越来越多,逻辑也变得越来越难以控制。yaWHTML5中文学习网 - HTML5先行者学习网

  通过参数配置应对变化的设计往往都是失败的设计yaWHTML5中文学习网 - HTML5先行者学习网

  易于导致复杂的逻辑控制,引发额外的偶发复杂度yaWHTML5中文学习网 - HTML5先行者学习网

  Forth Attempt: Abstracting over CriteriayaWHTML5中文学习网 - HTML5先行者学习网

  为此需要抽象,使其遍历的算法与查找的标准能够独立地变化,互不影响。yaWHTML5中文学习网 - HTML5先行者学习网

  @interface ProductSpec : NSObjectyaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)product;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  此刻filter的算法逻辑得到封闭,当然函数名需要重命名,使其算法实现更加具有普遍性。yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findProducts:(NSArray *)products bySpec:(ProductSpec *)specyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if ([spec satisfy:product]) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  通过可复用的类来封装各种变化,让变化的因素控制在最小的范围内。yaWHTML5中文学习网 - HTML5先行者学习网

  @interface ColorSpec()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, assign) ProductColor color;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation ColorSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)specWithColor:(ProductColor)coloryaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  ColorSpec *spec = [[ColorSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  spec.color = color;yaWHTML5中文学习网 - HTML5先行者学习网

  return spec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return product.color == RED;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @interface BelowWeightSpec()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, assign) float limit;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation BelowWeightSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)specWithBelowWeight:(float)limityaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  BelowWeightSpec *spec = [[BelowWeightSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  spec.limit = limit;yaWHTML5中文学习网 - HTML5先行者学习网

  return spec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return (product.weight < _limit);yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  用户的接口也变得简单多了,而且富有表现力。yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products bySpec:[ColorSpec specWithColor:RED]];yaWHTML5中文学习网 - HTML5先行者学习网

  这是经典的OO设计,如果熟悉设计模式的读者对此已经习以为常了。设计模式是好东西,但往往被滥用。为此不能依葫芦画瓢,死板照抄,而是为了得到更简单的设计而引入设计模式的,这个过程是很自然的。yaWHTML5中文学习网 - HTML5先行者学习网

  与大师们交流,问究此处为何引入设计模式,得到的答案:直觉。忘记所有设计模式吧,管它是不是模式,如果设计是简单的,这就是模式。yaWHTML5中文学习网 - HTML5先行者学习网

  另外还有一个明显的坏味道,ColorSpec和BelowWeightSpec都需要继承ProductSpec,都需要定义一个构造函数和一个私有的字段,并重写satisfy方法,这些都充斥着重复的结构。yaWHTML5中文学习网 - HTML5先行者学习网

  是不是觉得目前的写法已经够用了? 莫急, 让我们来看看下个需求yaWHTML5中文学习网 - HTML5先行者学习网

  需求4:查找所有颜色为红色,并且重量小于10的所有产品yaWHTML5中文学习网 - HTML5先行者学习网

  Firth Attempt: Composite CriteriayaWHTML5中文学习网 - HTML5先行者学习网

  按照既有的代码结构,往往易于设计出类似ColorAndBelowWeightSpec的实现。yaWHTML5中文学习网 - HTML5先行者学习网

  @interface ColorAndBelowWeigthSpec()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, assign) ProductColor color;yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, assign) float limit;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation ColorAndBelowWeigthSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)specWithColor:(ProductColor)color beloWeigth:(float)limityaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  ColorAndBelowWeigthSpec *spec = [[ColorAndBelowWeigthSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  spec.color = color;yaWHTML5中文学习网 - HTML5先行者学习网

  spec.limit = limit;yaWHTML5中文学习网 - HTML5先行者学习网

  return spec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return product.color == _color || (product.weight < _limit);yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  存在两个明显的坏味道:yaWHTML5中文学习网 - HTML5先行者学习网

  包含and的命名往往是违背单一职责的信号灯yaWHTML5中文学习网 - HTML5先行者学习网

  ColorAndBelowWeightSpec的实现与ColorSpec,BelowWeightSpec之间存在明显的重复yaWHTML5中文学习网 - HTML5先行者学习网

  此刻,需要寻找更本质的抽象来表达设计,and/or/not语义可以完美解决这类问题。yaWHTML5中文学习网 - HTML5先行者学习网

  Composite Spec: AndSpec, OrSpec, NotSpecyaWHTML5中文学习网 - HTML5先行者学习网

  Atomic Spec:ColorSpec, BeblowWeightSpecyaWHTML5中文学习网 - HTML5先行者学习网

  @interface AndSpec()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, strong) NSArray *specs;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation AndSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)spec:(ProductSpec *)spec, ... NS_REQUIRES_NIL_TERMINATIONyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  va_list args;yaWHTML5中文学习网 - HTML5先行者学习网

  va_start( args, spec );yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *mArray = [@[spec] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for ( ;; )yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  id tempSpec = va_arg( args, id );yaWHTML5中文学习网 - HTML5先行者学习网

  if (tempSpec == nil)yaWHTML5中文学习网 - HTML5先行者学习网

  break;yaWHTML5中文学习网 - HTML5先行者学习网

  [mArray addObject:tempSpec];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  va_end( args );yaWHTML5中文学习网 - HTML5先行者学习网

  AndSpec *andSpec = [[AndSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  andSpec.specs = [mArray copy];yaWHTML5中文学习网 - HTML5先行者学习网

  return andSpec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  for (ProductSpec *spec in _specs) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (![spec satisfy:product]) {yaWHTML5中文学习网 - HTML5先行者学习网

  return NO;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return YES;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @interface OrSpec ()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, strong) NSArray *specs;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation OrSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)spec:(ProductSpec *)spec, ... NS_REQUIRES_NIL_TERMINATIONyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  va_list args;yaWHTML5中文学习网 - HTML5先行者学习网

  va_start( args, spec );yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *mArray = [@[spec] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for ( ;; )yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  id tempSpec = va_arg( args, id );yaWHTML5中文学习网 - HTML5先行者学习网

  if (tempSpec == nil)yaWHTML5中文学习网 - HTML5先行者学习网

  break;yaWHTML5中文学习网 - HTML5先行者学习网

  [mArray addObject:tempSpec];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  va_end( args );yaWHTML5中文学习网 - HTML5先行者学习网

  OrSpec *orSpec = [[OrSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  orSpec.specs = [mArray copy];yaWHTML5中文学习网 - HTML5先行者学习网

  return orSpec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  for (ProductSpec *spec in _specs) {yaWHTML5中文学习网 - HTML5先行者学习网

  if ([spec satisfy:product]) {yaWHTML5中文学习网 - HTML5先行者学习网

  return YES;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return NO;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @interface NotSpec ()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, strong) ProductSpec *spec;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation NotSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)spec:(ProductSpec *)specyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NotSpec *notSpec = [[NotSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  notSpec.spec = spec;yaWHTML5中文学习网 - HTML5先行者学习网

  return notSpec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  if (![_spec satisfy:product]) {yaWHTML5中文学习网 - HTML5先行者学习网

  return YES;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return NO;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  可以通过AndSpec组合ColorSpec, BelowWeightSpec来实现需求,简单漂亮,并且富有表达力。yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products bySpec:[AndSpec spec:[ColorSpec specWithColor:RED], [BelowWeightSpec specWithBelowWeight:10], nil]];yaWHTML5中文学习网 - HTML5先行者学习网

  但这样的设计存在两个严重的坏问道:yaWHTML5中文学习网 - HTML5先行者学习网

  AndSpec与OrSpec存在明显的代码重复,OO设计的第一个直觉就是通过抽取基类来消除重复。yaWHTML5中文学习网 - HTML5先行者学习网

  @interface CombinableSpec ()yaWHTML5中文学习网 - HTML5先行者学习网

  @property (nonatomic, strong) NSArray *specs;yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation CombinableSpecyaWHTML5中文学习网 - HTML5先行者学习网

  + (instancetype)spec:(CombinableSpec *)spec, ... NS_REQUIRES_NIL_TERMINATIONyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  va_list args;yaWHTML5中文学习网 - HTML5先行者学习网

  va_start( args, spec );yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *mArray = [@[spec] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for ( ;; )yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  id tempSpec = va_arg( args, id );yaWHTML5中文学习网 - HTML5先行者学习网

  if (tempSpec == nil)yaWHTML5中文学习网 - HTML5先行者学习网

  break;yaWHTML5中文学习网 - HTML5先行者学习网

  [mArray addObject:tempSpec];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  va_end( args );yaWHTML5中文学习网 - HTML5先行者学习网

  CombinableSpec *combinableSpec = [[CombinableSpec alloc] init];yaWHTML5中文学习网 - HTML5先行者学习网

  combinableSpec.specs = [mArray copy];yaWHTML5中文学习网 - HTML5先行者学习网

  return combinableSpec;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (BOOL)satisfy:(Product *)productyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  for (ProductSpec *spec in _specs) {yaWHTML5中文学习网 - HTML5先行者学习网

  if ([spec satisfy:product] == _shortcut) {yaWHTML5中文学习网 - HTML5先行者学习网

  return _shortcut;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return !_shortcut;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation AndSpecyaWHTML5中文学习网 - HTML5先行者学习网

  - (instancetype)inityaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  self = [super init];yaWHTML5中文学习网 - HTML5先行者学习网

  if (self) {yaWHTML5中文学习网 - HTML5先行者学习网

  self.shortcut = NO;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return self;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  @implementation OrSpecyaWHTML5中文学习网 - HTML5先行者学习网

  - (instancetype)inityaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  self = [super init];yaWHTML5中文学习网 - HTML5先行者学习网

  if (self) {yaWHTML5中文学习网 - HTML5先行者学习网

  self.shortcut = YES;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return self;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  @endyaWHTML5中文学习网 - HTML5先行者学习网

  大堆的初始化方法让人眼花缭乱yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products bySpec:[NotSpec spec:[AndSpec spec:[ColorSpec specWithColor:RED], [BelowWeightSpec specWithBelowWeight:10], nil]]];yaWHTML5中文学习网 - HTML5先行者学习网

  Sixth Attempt: Using DSLyaWHTML5中文学习网 - HTML5先行者学习网

  可以引入DSL改善程序的可读性,让代码更具表达力。yaWHTML5中文学习网 - HTML5先行者学习网

  我们先添加一些DSL:yaWHTML5中文学习网 - HTML5先行者学习网

  static ProductSpec *COLOR(ProductColor color)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return [ColorSpec specWithColor:RED];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  static ProductSpec *BELOWWEIGHT(float limit)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return [BelowWeightSpec specWithBelowWeight:limit];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  static ProductSpec *AND(ProductSpec *spec1, ProductSpec *spec2)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return [AndSpec spec:spec1, spec2, nil];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  static ProductSpec *OR(ProductSpec *spec1, ProductSpec *spec2)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return [OrSpec spec:spec1, spec2, nil];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  static ProductSpec *NOT(ProductSpec *spec)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return [NotSpec spec:spec];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  这样我们的代码表现起来就是这样的yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products bySpec:NOT(AND(COLOR(RED), BELOWWEIGHT(10)))];yaWHTML5中文学习网 - HTML5先行者学习网

  Seventh Attempt: Using a Lambda ExpressionyaWHTML5中文学习网 - HTML5先行者学习网

  可以使用Block改善设计,增强表达力。yaWHTML5中文学习网 - HTML5先行者学习网

  - (NSArray *)findProducts:(NSArray *)products byBlock:(BOOL (^)())blockyaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  NSMutableArray *list = [@[] mutableCopy];yaWHTML5中文学习网 - HTML5先行者学习网

  for (Product *product in products) {yaWHTML5中文学习网 - HTML5先行者学习网

  if (block(product)) {yaWHTML5中文学习网 - HTML5先行者学习网

  [list addObject:product];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  return list;yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  代码现在开起来是这个样子yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products byBlock:^BOOL(id p) {return [p color] == RED;}];yaWHTML5中文学习网 - HTML5先行者学习网

  构造DSL,复用这些BlockyaWHTML5中文学习网 - HTML5先行者学习网

  ProductSpecBlock color(ProductColor color)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return ^BOOL(id p) {return [p color] == color;};yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  ProductSpecBlock weightBelow(float limit)yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  return ^BOOL(id p) {return [p weight] < limit;};yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  - (void)test7_2yaWHTML5中文学习网 - HTML5先行者学习网

  {yaWHTML5中文学习网 - HTML5先行者学习网

  [self findProducts:_products byBlock:color(RED)];yaWHTML5中文学习网 - HTML5先行者学习网

  }yaWHTML5中文学习网 - HTML5先行者学习网

  Eighth attempt: Using NSPredicateyaWHTML5中文学习网 - HTML5先行者学习网

  还可以使用标准库yaWHTML5中文学习网 - HTML5先行者学习网

  [self.products filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weight > 10"]];yaWHTML5中文学习网 - HTML5先行者学习网

  结束yaWHTML5中文学习网 - HTML5先行者学习网

  今天的编码就到此为止了, 这篇文章本是Horance所写, 笔者将用OC实现了一遍.如果咱们不是iOS Developer的话, 还是有其他attempt的, 如泛型.yaWHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助