iOS 设计模式 阅读笔记

第一章,你好,设计模式html

图书相关的一些资源ios

http://www.ocdesignpatterns.com/git

源代码下载地址 www.apress.comgithub

设计模式是为特定场景下的问题而定制的解决方案。算法

 针对接口编程,而不是针对实现编程编程

接口定义了类型。类继承与借口继承的关系canvas

类继承是经过复用父类的功能,来定义对象新的实现的一种机制。设计模式

使用接口的好处:网络

只要对象符合客户端所要求的接口,客户端就没必要在乎所使用对象的确切类型。数据结构

客户端只知道定义接口的协议或者抽象类,所以客户端对对象的类一无所知。

第3章 原型模式 Prototype

原型模式:使用原型实例指定建立对象的种类,并经过复制这个原型建立新的对象。

第4章 工厂模式

对调用的类来讲,只须要知道事物的基类和工厂的实现类就能够,

返回的是抽象类。

 

抽象工厂
CanvasViewGenerator.h


#import "CanvasView.h"
@interface CanvasViewGenerator :NSObject

- (CanvasVIew *)canvasViewWithFrame:(CGRect)aFrame;

@end

CanvasViewGenerator.m

#import "CanvasViewGenerator.h"
@implement CanvasViewGenerator

- (CanvasView *)canvasViewWithFrame:(CGRect)aFrame{
   return [[CanvasView alloc]initWithFrame:aFrame];

}



@end


抽象实体


实现工厂
PaperCanvasViewGenerator.h


#import "CanvasViewGenerator.h"
#import "PaperCanvasView.h"
@interface PaperCanvasViewGenerator :CanvasViewGenerator

- (CanvasVIew *)canvasViewWithFrame:(CGRect)aFrame;

@end

PaperCanvasViewGenerator.m

#import "PaperCanvasViewGenerator.h"
@implement PaperCanvasViewGenerator

- (CanvasView *)canvasViewWithFrame:(CGRect)aFrame{
   return [[CanvasView alloc]initWithFrame:aFrame];

}


ClothCanvasViewGenerator.h

#import "ClothCanvasViewGenerator.h"
#import "ClothCanvasView.h"

@interface ClothCanvasViewGenerator :CanvasViewGenerator

- (CanvasVIew *)canvasViewWithFrame:(CGRect)aFrame;

@end

ClothCanvasViewGenerator.m

#import "ClothCanvasViewGenerator.h"
@implement ClothCanvasViewGenerator

- (CanvasView *)canvasViewWithFrame:(CGRect)aFrame{
   return [[ClothCanvasView alloc]initWithFrame:aFrame];

}


实现实体

#import <UIKit/UIKit.h>
#import "CanvasView.h"
#import "PaperCanvasView.h"
@interface PaperCanvasView:CanvasView

    //私有变量

    //私有方法

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        UIImage *backgroundImage = [UIImage imageNamed:@"paper"];
        UIImageView *backgroundView = [[UIImageView alloc]initWithImage:backgroundImage];
        [self addSubview:backgroundView];
    }
    return self;
}

@end

#import <UIKit/UIKit.h>
#import "CanvasView.h"
#import "ClothCanvasView.h"
@interface ClothCanvasView:CanvasView

    //私有变量

    //私有方法

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        UIImage *backgroundImage = [UIImage imageNamed:@"cloth"];
        UIImageView *backgroundView = [[UIImageView alloc]initWithImage:backgroundImage];
        [self addSubview:backgroundView];
    }
    return self;
}

@end



//客户端调用工厂方法,客户端和具体的实现是解耦的,
//若是后续须要增长一种新的画布,客户端不须要修改已经有的代码,只须要在须要调用的地方添加便可

- (void)viewDidLoad{

   CanvasViewGenerator *defaultGenerator = [[ClothCanvasViewGenerator alloc]init];
   CanvasView *aCanvasView = [self loadCanvasViewWithGenerator:defaultGenerator];
   

}


- (void)loadCanvasViewWithGenerator:(CanvasViewGenerator *)generator{
     [canvasView_ removeFromSuperView];
     CGRect aFrame = CGRectMake(0,0,320,436);
     CanvasView *aCanvasView = [generator canvasViewWithFrame:aFrame];
     [self setCanvasView:aCanvasView];
     [self.view addSubview:aCanvasView];

}

第5章 抽象工厂

抽象工厂:提供一个建立一系列相关或互相依赖对象的接口,而无需指定他们具体的类。

简单工厂,工厂方法,抽象工厂方法的区别

http://www.cnblogs.com/zhangchenliang/p/3700820.html

 

第6章 生成器

生成器:将一个复杂对象的构建和表现分离,相同的构建能够建立不一样的表现。

 

第7章 单例

 

第三部分 接口适配

第8章 适配器

适配器模式:将一个类的接口转换为客户但愿的另一个接口,适配器模式使得因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。

应用场景,

已有类接口与需求不匹配,

想要一个复用的类,该类可以与不兼容的其余类写做,

 

用块语法实现适配器

 

 

第9章 桥接

桥接模式:将抽象部分与实现部分分类,使他们均可以独立地变化

使用场景

抽象和实现均可以经过子类化独立进行扩展

对抽象的实现进行修改不该影响客户端代码

若是每一个实现须要额外的子类以细化抽象,则说明有必要把他们分红2个部分

想在带有不一样抽象接口的多个对象之间共享一个实现。

 

 

 

 

第10章 外观

外观:为系统中的一组接口提供一个统一的接口,外观定义了一个高层接口,让子系统更易于使用。

 

汽车类,负责 启动,加油等操做

#import <Foundation/Foundation.h>


@interface Car : NSObject 
{

}

// ...

- (void) releaseBrakes;
- (void) changeGears;
- (void) pressAccelerator;
- (void) pressBrakes;
- (void) releaseAccelerator;

// ...

@end



#import "Car.h"


@implementation Car

- (void) releaseBrakes
{
	
}

- (void) changeGears
{
	
}

- (void) pressAccelerator
{
	
}

- (void) pressBrakes
{
	
}

- (void) releaseAccelerator
{
	
}

计价器,负责计算价格

#import <Foundation/Foundation.h>


@interface Taximeter : NSObject 
{

}

- (void) start;
- (void) stop;

@end

#import "Taximeter.h"


@implementation Taximeter

- (void) start
{
	
}

- (void) stop
{
	
}

@end

 

 

司机类,负责开车和计价,可是给客户端调用的时候提供了惟一的方法 - (void) driveToLocation:(CGPoint) x;方便客户端调用

#import "Taximeter.h"


@implementation Taximeter

- (void) start
{
	
}

- (void) stop
{
	
}

@end


#import "CabDriver.h"


@implementation CabDriver

- (void) driveToLocation:(CGPoint) x
{
  // ...
  
  // set off the taximeter
  Taximeter *meter = [[Taximeter alloc] init];
  [meter start];
  
  // operate the vehicle
  // until location x is reached
  Car *car = [[Car alloc] init];
  [car releaseBrakes];
  [car changeGears];
  [car pressAccelerator];
  
  // ...
  
  // when it's reached location x
  // then stop the car and taximeter
  [car releaseAccelerator];
  [car pressBrakes];
  [meter stop];
  
  // ...
}

@end

调用代码

 CabDriver *cab = [[CabDriver alloc]init];

  [cab driveToLocation:CGPointMake(100, 100)];

 

    

 

 

第11章 中介者

中介者模式,用一个对象来封装一系列对象的交互方式。中介者使各对象不须要互相饮用,从而使其耦合松散,并且能够独立地改变他们之间的交互。

使用场景:对象之间的交互虽然定义明确然而很是复杂,致使一组对象彼此互相依赖

由于对象引用了许多其余对象并与其通信,致使对象难以复用

想要定制一个分部在多个类的逻辑或行为,又不想生成太多子类

第12章 观察者

观察者模式:定义对象见的一种一对多的依赖关系,当一个对象的状态发生改变时,依赖于他的对象都获得通知并被自动更新。

使用场景:

有2种抽象类型互相依赖,将它们封装在各自的对象中,就能够对它们单独进行改变和复用

对一个对象的改变须要同时改变其余对象,而不知道具体有多少对象有待改变

一个对象必须通知其余对象,而它又不知道其余对象是什么。

通知 和键值观察实现了观察者模式

第13章 组合模式

组合模式:将对象组合成树状结构以标示 部分-总体的层次结构,组合使得用户对单个对象和组合对象的使用具备一致性。

使用场景:

想得到对象抽象的树形表示

想让客户端统一处理组合结构中的全部对象

Cocoa Touch中的UIView 就是一个层次结构的例子。

第14章 迭代器

迭代器:提供一种方法顺序访问一个聚合对象中的各元素,而又不需暴露该对象的内部表示。

使用场景:须要访问组合对象的内容,而又不需暴露其内部表示

须要经过多种方式遍历组合对象

须要提供一个统一的接口,用来便利各类类型的组合对象。

NSEnumerator实现了迭代器模式。可以顺序遍历各类集合

快速枚举 forin,使用了指针运算

NSArray有个方法(void)makeObjectsPerformSelector:(SEL)aSelector;

第15章 访问者

访问者模式:表示一个做用于某对象结构中的各元素的操做,它让咱们能够在不改变各元素的类的前提下定义做用于这些元素的新操做。

应用场景:一个复杂的对象结构包含不少其它对象,它们有不一样的接口(好比组合体),这些对象实施一些依赖于其它类型的操做。

须要对一个组合结构中的对象进行不少不相关的操做,可是不想让这些操做污染这些对象的类。能够将相关的操做集中起来,定义在一个访问者类中,并在须要在访问者中定义的操做时使用它。

定义复杂结构的类不多做修改,但常常须要向其添加新的操做。

 

 

第16章 装饰

装饰模式:动态地给一个对象添加一些额外的职责,就扩展功能来讲,装饰模式相比生成子类更为灵活。

想要在不影响其它对象的状况下,以动态,透明的方式给耽搁对象添加职责。

想要扩展一个类的行为,却作不到。类定义可能被隐藏,没法进行子类化,或者,对类的每一个行为的扩展,为支持每种功能的组合将产生大量的子类。

对类的职责的扩展是可选的。

能够经过 forwardingTargetForSelector:(SEL)aSelector 的方法或者

能够经过范畴实现装饰模式

 

定义基类的变化扩展类

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface UIImage (BaseFilter)

- (CGContextRef) beginContext;
- (UIImage *) getImageFromCurrentImageContext;
- (void) endContext;

@end



#import "UIImage+BaseFilter.h"


@implementation UIImage (BaseFilter)

- (CGContextRef) beginContext
{
  // Create a graphics context with the target size
  // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions 
  // to take the scale into consideration
  // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
  CGSize size = [self size];
  if (NULL != UIGraphicsBeginImageContextWithOptions)
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
  else
    UIGraphicsBeginImageContext(size);
  
  CGContextRef context = UIGraphicsGetCurrentContext();
  
  return context;
}

- (UIImage *) getImageFromCurrentImageContext
{
  [self drawAtPoint:CGPointZero];
  
  // Retrieve the UIImage from the current context
  UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
  
  return imageOut;
}

- (void) endContext
{
  UIGraphicsEndImageContext();
}

更加具体的一个扩展

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface UIImage (Transform)

- (UIImage *) imageWithTransform:(CGAffineTransform)transform;

@end


#import "UIImage+Transform.h"
#import "UIImage+BaseFilter.h"

@implementation UIImage (Transform)

- (UIImage *) imageWithTransform:(CGAffineTransform)transform
{
  CGContextRef context = [self beginContext];
  
  // setup transformation
  CGContextConcatCTM(context, transform);
  
  // Draw the original image to the context
  UIImage *imageOut = [self getImageFromCurrentImageContext];
  
  [self endContext];
  
  return imageOut;
}

@end

 

第17章 责任链

责任链模式:使多个对象都有机会请求处理请求,从而避免请求的发送者何接收者之间发生耦合。此模式将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

使用场景:有多个对象能够处理请求,而处理程序直邮在运行时才能肯定。

向一组对象发出请求,而不想显式指定处理请求的特定处理程序。

一个攻击游戏人物护甲的演示

攻击基类(什么也没有。。。)

#import <Foundation/Foundation.h>


@interface Attack : NSObject 
{

}

@end

#import "Attack.h"


@implementation Attack

@end

护甲基类,有一个下一个处理者的属性,基类中定义了处理攻击的行为,会调用下一个处理者的该方法

#import <Foundation/Foundation.h>
#import "Attack.h"

@interface AttackHandler : NSObject 
{
  @private
  AttackHandler *nextAttackHandler_;
}

@property (nonatomic, retain) AttackHandler *nextAttackHandler;

- (void) handleAttack:(Attack *)attack;

@end


#import "AttackHandler.h"


@implementation AttackHandler

@synthesize nextAttackHandler=nextAttackHandler_;


- (void) handleAttack:(Attack *)attack
{
  [nextAttackHandler_ handleAttack:attack];
}

@end

金属护甲能够识别处理SwordAttack,若是处理成功了,伤害再也不继续传递

#import <Foundation/Foundation.h>
#import "AttackHandler.h"

@interface MetalArmor : AttackHandler
{

}

// overridden method
- (void) handleAttack:(Attack *)attack;

@end


#import "MetalArmor.h"
#import "SwordAttack.h"

@implementation MetalArmor

- (void) handleAttack:(Attack *)attack
{
  if ([attack isKindOfClass:[SwordAttack class]])
  {
    // no damage beyond this armor
    NSLog(@"%@", @"No damage from a sword attack!");
  }
  else 
  {
    NSLog(@"I don't know this attack: %@", [attack class]);
    [super handleAttack:attack];
  }
}

@end

水晶护甲能够识别处理MagicFireAttack,若是处理成功了,伤害再也不继续传递,若是不能处理继续传递。

#import <Foundation/Foundation.h>
#import "AttackHandler.h"

@interface CrystalShield : AttackHandler
{

}

// overridden method
- (void) handleAttack:(Attack *)attack;

@end



#import "CrystalShield.h"
#import "MagicFireAttack.h"

@implementation CrystalShield

- (void) handleAttack:(Attack *)attack
{
  if ([attack isKindOfClass:[MagicFireAttack class]])
  {
    // no damage beyond this shield
    NSLog(@"%@", @"No damage from a magic fire attack!");
  }
  else 
  {
    NSLog(@"I don't know this attack: %@", [attack class]);
    [super handleAttack:attack];
  }
}

@end

 

游戏人物,接收全部的伤害

#import <Foundation/Foundation.h>
#import "AttackHandler.h"

@interface Avatar : AttackHandler
{

}

// overridden method
- (void) handleAttack:(Attack *)attack;

@end

#import "Avatar.h"


@implementation Avatar

- (void) handleAttack:(Attack *)attack
{
  // when an attack reaches this point,
  // I'm hit.
  // actual points taken off depends on
  // the type of attack.
  NSLog(@"Oh! I'm hit with a %@!", [attack class]);
}


@end

 

这个例子里面的伤害实现类都是基本没有内容的。。。

#import <Foundation/Foundation.h>
#import "Attack.h"

@interface SwordAttack : Attack
{

}

@end

#import "SwordAttack.h"


@implementation SwordAttack

@end



#import <Foundation/Foundation.h>
#import "Attack.h"

@interface MagicFireAttack : Attack
{

}

@end

#import "MagicFireAttack.h"


@implementation MagicFireAttack

@end





#import <Foundation/Foundation.h>
#import "Attack.h"

@interface LightningAttack : Attack
{

}

@end

#import "LightningAttack.h"


@implementation LightningAttack

@end

 

客户端调用

- (void)viewDidLoad
{
  [super viewDidLoad];
  
  // create a new avatar
  AttackHandler *avatar = [[[Avatar alloc] init] autorelease];
  
  // put it in metal armor
  AttackHandler *metalArmoredAvatar = [[[MetalArmor alloc] init] autorelease];
  [metalArmoredAvatar setAttackHandler:avatar];
  
  // then add a crytal shield
  // to the avatar who's in 
  // a metal armor
  AttackHandler *superAvatar = [[[CrystalShield alloc] init] autorelease];
  [superAvatar setAttackHandler:metalArmoredAvatar];
  
  // ... some other actions
  
  // attack the avatar with
  // a sword
  Attack *swordAttack = [[[SwordAttack alloc] init] autorelease];
  [superAvatar handleAttack:swordAttack];
  
  // then attack the avatar with
  // magic fire
  Attack *magicFireAttack = [[[MagicFireAttack alloc] init] autorelease];
  [superAvatar handleAttack:magicFireAttack];
  
  // now there is a new attack
  // with lightning...
  Attack *lightningAttack = [[[LightningAttack alloc] init] autorelease];
  [superAvatar handleAttack:lightningAttack];
  
  // ... further actions
}

 

第七部分

18模板方法

模板方法:定义一个操做中算法的骨架,而将一些步骤延迟到子类种中,模板方法使子类能够重定义算法的某些特定步骤而不改变该算法的结构。

使用场景:

须要一次性实现算法的不变部分,而将可变的行为留给子类来实现。

子类的共同行为应该被提取出来放到公共类中,以免代码的重复。现有代码的差异应该被分离为新的操做。而后用一个调用这些新操做的木板方法来替换这些不一样的代码。

须要控制子类的扩展。能够定义一个在特定点调用钩子操做的模板方法。子类能够经过对钩子操做的实如今这些点扩展功能。

制做三明治的例子来讲

定义抽象基类,制做三明治的通常步骤

//AnySandwich.h


#import <Foundation/Foundation.h>


@interface AnySandwich : NSObject 
{

}

- (void) make;

// Steps to make a sandwich
- (void) prepareBread;
- (void) putBreadOnPlate;
- (void) addMeat;
- (void) addCondiments;
- (void) extraStep;
- (void) serve;

@end


//AnySandwich.m
#import "AnySandwich.h"


@implementation AnySandwich

- (void) make
{
  [self prepareBread];
  [self putBreadOnPlate];
  [self addMeat];
  [self addCondiments];
  [self extraStep];
  [self serve];
}

- (void) putBreadOnPlate
{
  // We need first to put bread on a plate for any sandwich.
}

- (void) serve
{
  // Any sandwich will be served eventually.
}

#pragma mark -
#pragma Details will be handled by subclasses

- (void) prepareBread
{
  
  [NSException raise:NSInternalInconsistencyException 
              format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
}

- (void) addMeat
{
  [NSException raise:NSInternalInconsistencyException 
              format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
}

- (void) addCondiments
{
  [NSException raise:NSInternalInconsistencyException 
              format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
}

- (void) extraStep{}

@end

 

汉堡类

//Hamburger.h

#import <Foundation/Foundation.h>
#import "AnySandwich.h"

@interface Hamburger : AnySandwich 
{

}

- (void) prepareBread;
- (void) addMeat;
- (void) addCondiments;
//- (void) extraStep;

// Hamburger specific methods
- (void) getBurgerBun;
- (void) addKetchup;
- (void) addMustard;
- (void) addBeefPatty;
- (void) addCheese;
- (void) addPickles;

@end

//Hamburger.m

#import "Hamburger.h"


@implementation Hamburger

- (void) prepareBread;
{
  [self getBurgerBun];
}

- (void) addMeat
{
  [self addBeefPatty];
}

- (void) addCondiments
{
  [self addKetchup];
  [self addMustard];
  [self addCheese];
  [self addPickles];
}

#pragma mark -
#pragma mark Hamburger Specific Methods

- (void) getBurgerBun
{
  // A hamburger needs a bun.
}

- (void) addKetchup
{
  // Before adding anything to a bun, we need to put ketchup.
}

- (void) addMustard
{
  // Then add some mustard.
}

- (void) addBeefPatty
{
  // A piece of beef patty is the main character in a burger.
}

- (void) addCheese
{
  // Let's just assume every burger has cheese.
}

- (void) addPickles
{
  // Then finally add some pickles to it.
}

@end

热狗类

//Hotdog.h

#import <Foundation/Foundation.h>
#import "AnySandwich.h"

@interface Hotdog : AnySandwich 
{
  
}

- (void) prepareBread;
- (void) addMeat;
- (void) addCondiments;
//- (void) extraStep;

// Hotdog specific methods
- (void) getHotdogBun;
- (void) addWiener;
- (void) addKetchup;
- (void) addMustard;
- (void) addOnion;

@end

//Hotdog.m

#import "Hotdog.h"


@implementation Hotdog

- (void) prepareBread
{
  [self getHotdogBun];
}

- (void) addMeat
{
  [self addWiener];
}

- (void) addCondiments
{
  [self addKetchup];
  [self addMustard];
  [self addOnion];
}

#pragma mark -
#pragma mark Hotdog Specific Methods

- (void) getHotdogBun
{
  // First of all, we need a hotdog bun.
}

- (void) addWiener
{
  // A nice piece of wiener is the main character here.
}

- (void) addKetchup
{
  // Every hotdog needs ketchup.
}

- (void) addMustard
{
  // I think mustard is also needed.
}

- (void) addOnion
{
  // I think adding onion is a good idea.
}

@end

 

19策略

策略模式:定义一系列的算法,把它们一个个封装起来,而且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。

一个类在其操做中使用多个条件语句来定义许多行为。咱们能够把相关的条件分支移到它们本身的策略类种功能。

须要算法的各类变体

须要避免把复杂的与算法相关的数据结构暴露给客户端。

- (BOOL)validateInput:(UITextField *)input error:(NSError **)error;

采用error参数能够传递错误信息,引用UITextField参数能够对输入框做相应的修改。

- (BOOL)validateInput:(UITextField*)input error:(NSError **)error{
    NSError *regError = nil;
    NSRegularExpression *regx = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]*$" options:NSRegularExpressionAnchorsMatchLines error:&regError];
    
    NSUInteger numberOfMatches = [regx numberOfMatchesInString:[input text] options:NSMatchingAnchored range:NSMakeRange(0, [[input text]length])];
    
    if (numberOfMatches == 0) {
        if (error != nil) {
            NSString *description =  NSLocalizedString(@"Input Validation Failed", @"") ;
            NSString *reason =   NSLocalizedString(@"The input can contain only numberic values", @"") ;
            NSArray *objArray = [NSArray arrayWithObjects:description,reason, nil];
            NSArray *keyArray = [NSArray arrayWithObjects:NSLocalizedDescriptionKey,NSLocalizedFailureReasonErrorKey, nil];
            NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:objArray forKeys:keyArray];
            *error = [NSError errorWithDomain:@"InptValidationErrorDomain" code:1001 userInfo:userInfo];
        }
        return NO;
        
        
    }
    
    
    return YES;
    
    
    
}

 

若是直接调用汉堡的基类,会报错

//不能够直接调用抽象基类,会报错

 AnySandwich * sandwich = [[AnySandwich alloc] init];
 
 [sandwich make];



//具体的子类能够直接调用
    
   
 AnySandwich *hotdog = [[Hotdog alloc]init];
    
[hotdog make];

 

 

20命令

命令模式:将请求封装为一个对象,从而可用不一样的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操做。

想让应用程序支持撤销与恢复。

想用对象参数话一个动做以执行操做,并用不一样命令对象来代替回调函数。

想要在不一样的时刻对请求进行指定,排序和执行。

想记录修改日日志,这样在系统故障时,这些修改可在后来重作一遍。

想让系统支持事务,事务封装了对数据的一系列修改。事务能够建模为命令对象。

NSInvocation

NSUndoManager

第八部分 性能与对象访问

第21章享元模式

享元模式(Flyweight pattern): 运用共享技术有效地支持大量细粒度的对象。

当知足全部条件时,天然会考虑使用这个模式:

应用程序使用不少对象

在内存中保存对象会影响内存性能

对象的多数特有状态能够放到外部而轻量化

移除外在状态后,能够用较少的共享对象替代原来的那组对象。

应用程序不依赖于对象标识,由于共享对象不能提供惟一的标识。

 

百花池 效果

定义了一个FlowerView用来展现花朵

//FlowerView.h 文件

#import <Foundation/Foundation.h>
#import "UIKit/UIKit.h"

@interface FlowerView : UIImageView 
  
@end

//FlowerView.m 文件

#import "FlowerView.h"

@implementation FlowerView

- (void) drawRect:(CGRect)rect
{
  [self.image drawInRect:rect];
}

@end

 定义了一个工厂方法来产生FlowerView

//FlowerFactory.h


#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum 
{
  kAnemone,
  kCosmos,
  kGerberas,
  kHollyhock,
  kJasmine,
  kZinnia,
  kTotalNumberOfFlowerTypes
} FlowerType;

@interface FlowerFactory : NSObject 
{
  @private
  NSMutableDictionary *flowerPool_;
}

- (UIView *) flowerViewWithType:(FlowerType)type;

@end

//FlowerFactory.m

#import "FlowerFactory.h"
#import "FlowerView.h"

@implementation FlowerFactory


- (UIView *) flowerViewWithType:(FlowerType)type
{
  // lazy-load a flower pool
  if (flowerPool_ == nil)
  {
    flowerPool_ = [[NSMutableDictionary alloc] 
                   initWithCapacity:kTotalNumberOfFlowerTypes];
  }
  
  // try to retrieve a flower
  // from the pool
  UIView *flowerView = [flowerPool_ objectForKey:[NSNumber 
                                                  numberWithInt:type]];
  
  // if the type requested
  // is not available then
  // create a new one and
  // add it to the pool
  if (flowerView == nil)
  {
    UIImage *flowerImage;
    
    switch (type) 
    {
      case kAnemone:
        flowerImage = [UIImage imageNamed:@"anemone.png"];
        break;
      case kCosmos:
        flowerImage = [UIImage imageNamed:@"cosmos.png"];
        break;
      case kGerberas:
        flowerImage = [UIImage imageNamed:@"gerberas.png"];
        break;
      case kHollyhock:
        flowerImage = [UIImage imageNamed:@"hollyhock.png"];
        break;
      case kJasmine:
        flowerImage = [UIImage imageNamed:@"jasmine.png"];
        break;
      case kZinnia:
        flowerImage = [UIImage imageNamed:@"zinnia.png"];
        break;
      default:
        break;
    } 
    
    flowerView = [[FlowerView alloc]
                   initWithImage:flowerImage];
    [flowerPool_ setObject:flowerView 
                    forKey:[NSNumber numberWithInt:type]];
  }
  
  return flowerView;
}

 

保存flowerview的状态

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>



@interface ExtrinsicFlowerState : NSObject
 

@property (nonatomic,strong) UIView *flowerView;

@property (nonatomic,assign) CGRect area;

@end


#import "ExtrinsicFlowerState.h"

@implementation ExtrinsicFlowerState

@end

 

控制器中调用代码

- (void)viewDidLoad {
    [super viewDidLoad];
    
 
    // construct a flower list
    FlowerFactory *factory = [[FlowerFactory alloc] init];
    NSMutableArray *flowerList = [[NSMutableArray alloc]
                                   initWithCapacity:500];
    
    
    for (int i = 0; i < 5000; ++i)
    {
        // retrieve a shared instance
        // of a flower flyweight object
        // from a flower factory with a
        // random flower type
        FlowerType flowerType = arc4random() % kTotalNumberOfFlowerTypes;
        UIView *flowerView = [factory flowerViewWithType:flowerType];
        
        // set up a location and an area for the flower
        // to display onscreen
        CGRect screenBounds = [[UIScreen mainScreen] bounds];
        CGFloat x = (arc4random() % (NSInteger)screenBounds.size.width);
        CGFloat y = (arc4random() % (NSInteger)screenBounds.size.height);
        NSInteger minSize = 10;
        NSInteger maxSize = 50;
        CGFloat size = (arc4random() % (maxSize - minSize + 1)) + minSize;
        
        // assign attributes for a flower
        // to an extrinsic state object
        ExtrinsicFlowerState * extrinsicState =[[ ExtrinsicFlowerState alloc]init];
        extrinsicState.flowerView = flowerView;
        extrinsicState.area = CGRectMake(x, y, size, size);
        
        // add an extrinsic flower state
        // to the flower list
        [flowerList addObject: extrinsicState ];
        
 
    }

    // add the flower list to
//     this FlyweightView instance
    FlyweightView *flyWeightView = [[FlyweightView alloc]initWithFrame:CGRectMake(0, 0, 320, 640)];
  
  
    flyWeightView.backgroundColor = [UIColor orangeColor];
   
    [flyWeightView setFlowerList:flowerList];
 
    [self.view addSubview:flyWeightView];
 
    
    // Do any additional setup after loading the view, typically from a nib.
}

这样处理比直接在self.view 上添加 UIImageView仍是节约了不少内存开销的,效果以下

22 代理

代理模式:为其它对象提供一种代理以控制对这个对象的访问。

须要一个远程代理,为处于不一样地质空间或者网络中的对象提供本地带遍。

须要一个虚拟代理,为根据要求建立重型的对象。

须要一个保护代理,来控制不一样访问权限对原对象的访问。

须要一个智能引用代理,经过对实体对象的引用来进行计数来管理内存。也能用户锁定实体对象,让其它对象不能修改它。

23备忘录

备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态,这样之后就可将该对象恢复到原来保存的状态。

Cocoa Touch NSKeyedArchiver NSKeyedUnarchiver

NSCoding 协议

 

 

 

 

参考资料

Pro Objective C Design Pattern for iOS Objective C编程之道iOS设计模式解析

https://github.com/iossvis/Objective-C-Design-Patterns-for-IOS----Carlo-Chung-book-s-code

相关文章
相关标签/搜索