前言
本文csdn地址:http://blog.csdn.net/game3108/article/details/51154428
本文主要以代码形式实现每一种设计模式,算是自己的一种复习和实践。相应的代码,也会放到github上。
本文的类图均来自于《Objective-C编程之道 iOS设计模式解析》。
本篇主要讲:
- 单例
- 原型
- 生成器
3.单例
概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
类图:
何时使用:
- 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问。
- 这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
主要用了三种方式去实现:
1.dispatch_once方式
#import <Foundation/Foundation.h>
@interface SingletonGCDObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonGCDObject.h"
@implementation SingletonGCDObject
+ (instancetype) sharedInstance{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@end
2.synchronized方式
#import <Foundation/Foundation.h>
@interface SingletonSynObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonSynObject.h"
static SingletonSynObject *singletonInstrance = nil;
@implementation SingletonSynObject
+ (instancetype) sharedInstance{
@synchronized (self) {
if ( singletonInstrance == nil )
singletonInstrance = [[SingletonSynObject alloc]init];
return singletonInstrance;
}
}
@end
3.initialize方式
#import <Foundation/Foundation.h>
@interface SingletonInitializeObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonInitializeObject.h"
static SingletonInitializeObject *singletonInstrance = nil;
@implementation SingletonInitializeObject
+ (void)initialize{
singletonInstrance = [[SingletonInitializeObject alloc]init];
}
+ (instancetype) sharedInstance{
return singletonInstrance;
}
@end
4.原型
概念:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象。
类图:
何时使用:
- 需要创建的对象应独立于其类型与创建方式。
- 要实例化的类是在运行时决定的。
- 不想要与产品层次相对应的工厂层次。
- 不同类的实例间的差异仅是状态的若干组合。因此复制相应数量的原型比手工实例化更加方便。
- 类不容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。
在Objective-C中,使用copy是最典型的原型的方式,而想使用copy方法,就要实现NSCopying的协议。具体代码如下:
#import <Foundation/Foundation.h>
@interface PrototypeObject : NSObject<NSCopying>
@property (nonatomic, strong) NSString *property1;
@property (nonatomic, assign) NSInteger property2;
@property (nonatomic, copy) NSString *property3;
@end
#import "PrototypeObject.h"
@implementation PrototypeObject
- (id)copyWithZone:(nullable NSZone *)zone{
PrototypeObject *object = [[[self class] allocWithZone:zone] init];
object.property1 = self.property1;
object.property2 = self.property2;
object.property3 = [self.property3 copy];
return object;
}
@end
5.生成器
概念:将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。
类图:
何时使用:
- 需要创建涉及各种部件的复杂对象。创建对象的算法应该独立于部件的装配方式。
- 构建过程需要以不同的方式构建对象。
代码场景:
一个新的主题乐园,需要指定一系列的活动计划,包括活动第几天,住在哪里,玩什么活动的门票等。
计划类:
#import <Foundation/Foundation.h>
@interface Planner : NSObject
@property (nonatomic, assign) NSInteger date;
@property (nonatomic, copy) NSString *ticket;
@property (nonatomic, copy) NSString *hotel;
@end
计划建造者的抽象:
#import <Foundation/Foundation.h>
#import "Planner.h"
@protocol AbstractBuilder <NSObject>
- (id<AbstractBuilder>) buildPlanner;
- (id<AbstractBuilder>) addDate:(NSInteger) date;
- (id<AbstractBuilder>) addHotel:(NSString *)hotel;
- (id<AbstractBuilder>) addTicket:(NSString *)ticket;
- (Planner *) getPlanner;
@end
计划建造者的实现
#import <Foundation/Foundation.h>
#import "AbstractBuilder.h"
@interface VacationBuilder : NSObject<AbstractBuilder>
@end
#import "VacationBuilder.h"
@interface VacationBuilder(){
Planner *_planner;
}
@end
@implementation VacationBuilder
- (id<AbstractBuilder>) buildPlanner{
_planner = nil;
_planner = [[Planner alloc]init];
return self;
}
- (id<AbstractBuilder>) addDate:(NSInteger) date{
_planner.date = date;
return self;
}
- (id<AbstractBuilder>) addHotel:(NSString *)hotel{
_planner.hotel = hotel;
return self;
}
- (id<AbstractBuilder>) addTicket:(NSString *)ticket{
_planner.ticket = ticket;
return self;
}
- (Planner *) getPlanner{
return _planner;
}
@end
乐园类:
#import <Foundation/Foundation.h>
#import "Planner.h"
#import "AbstractBuilder.h"
@interface VacationPark : NSObject
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder;
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder;
@end
#import "VacationPark.h"
#import "VacationBuilder.h"
@implementation VacationPark
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder{
[builder buildPlanner];
[builder addDate:1];
[builder addHotel:@"如家"];
[builder addTicket:@"过山车"];
return [builder getPlanner];
}
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder{
[builder buildPlanner];
[builder addDate:2];
[builder addHotel:@"汉庭"];
[builder addTicket:@"鬼屋"];
return [builder getPlanner];
}
@end
总结:
1.应该尽量少的使用单例,因为单例的生命周期控制会比较麻烦。尤其是当添加了撤销单例以后。参考链接Avoiding Singleton Abuse(译文:避免滥用单例)。
2.生成器与抽象工厂的对比:
生成器:
- 构建复杂对象
- 以多个步骤构建对象
- 以多种方式构建对象
- 在构建过程的最后一步返回产品
- 专注一个特定产品
抽象工厂:
- 构建简单或复杂对象
- 以单一步骤构建对象
- 以单一方式构建对象
- 立即返回产品
- 强调一套产品
参考资料
1.《Objective-C编程之道 iOS设计模式解析》
2.《Head First设计模式》