您的位置:首页 > 移动开发 > Objective-C

使用Object-C实现23种设计模式之原型模式

2016-05-24 21:07 453 查看
今天讲解一下最后一个创建型模式——原型模式,在讲解原型模式之前,先说两个概念,深拷贝和浅拷贝,相信学过C或者C++的人都应该了解什么是深拷贝什么是浅拷贝。

深拷贝:增加一个指针并且指向一个新的内存空间,使新的内存空间内存储的数据与被拷贝对象的数据相同。

浅拷贝:增加一个指针只想被拷贝的对象。

下面举一个特别通俗的例子:某农夫家有两个儿子,该农夫给大儿子买了一套房子,二儿子也想要同样的房子,于是农夫又买下一套构造一样的房子,并且把内部装修的跟大儿子的房子一模一样后,给了二儿子,这就是深拷贝;同样的示例,农夫给大儿子买房子后,二儿子想要同样的房子,但是农夫资金不足,就给二儿子配了一把大儿子家房子的钥匙,给了二儿子,这就是浅拷贝。

彻底了解深拷贝与浅拷贝之后,再去学习下面的原型模式:

所谓原型模式,就是根据一个对象创建一个相同的对象,这样的好处是,在创建对象是,节省了很多对对象的属性进行初始化的过程,在很大程度上提高了代码质量以及开发效率。

此外,原型模式很少单独出现,他的出现一般伴随着其他的设计模式,然而,原型模式与单例模式在实现上又有着冲突,所以,两者不可能同时出现。

首先,看下面一个实例:

在某高中男生宿舍中,有四个人,二者四个人恰恰是四胞胎(举例需求,如有雷同,纯属巧合>-<),死人无论在身高、体重等方面,不尽相同,再次,假设死人名字分别为张一,张二,张三,张四,家庭地址为山东省,性别均为男,下面构建一个Person类,假设其只有姓、名、性别、家庭住址四个属性。

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject<NSCopying>

@property (nonatomic) NSString* firstName;
@property (nonatomic) NSString* lastName;
@property (nonatomic) NSString* sex;
@property (nonatomic) NSString* address;

-(id)initWithFirstName:(NSString*)firstName andLastName:(NSString*)lastName andSex:(NSString*)sex andAddress:(NSString*)address;

@end


Person.m

#import "Person.h"

@implementation Person

@synthesize firstName = _firstName;
@synthesize lastName = _lastName;
@synthesize sex = _sex;
@synthesize address = _address;

-(id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName andSex:(NSString *)sex andAddress:(NSString *)address{
if(self = [super init]){
_firstName = firstName;
_lastName = lastName;
_sex = sex;
_address = address;
}
return self;
}

-(id)copyWithZone:(NSZone *)zone{

Person* per = [[[self class]allocWithZone:zone]initWithFirstName:_firstName andLastName:_lastName andSex:_sex andAddress:_address];

return per;
}

@end

这里的关键是实现NSCopying协议,以及对协议中copyWithZone方法的实现。

下面看一下使用原型模式的好处,如果不使用原型模式,则创建者兄弟四人具体实例的过程应如下所示:

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person* per1 = [[Person alloc]initWithFirstName:@"张" andLastName:@"一" andSex:@"男" andAddress:@"山东省"];
Person* per2 = [[Person alloc]initWithFirstName:@"张" andLastName:@"二" andSex:@"男" andAddress:@"山东省"];
Person* per3 = [[Person alloc]initWithFirstName:@"张" andLastName:@"三" andSex:@"男" andAddress:@"山东省"];
Person* per4 = [[Person alloc]initWithFirstName:@"张" andLastName:@"四" andSex:@"男" andAddress:@"山东省"];
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per1,per1.firstName,per1.lastName,per1.sex,per1.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per2,per2.firstName,per2.lastName,per2.sex,per2.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per3,per3.firstName,per3.lastName,per3.sex,per3.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per4,per4.firstName,per4.lastName,per4.sex,per4.address);
}
return 0;
}


输出结果为:

2016-05-24 21:05:01.511 设计模式之五原型模式[860:29812]内存地址:<Person:
0x1004001e0>
姓:张名:一性别:男地址:山东省

2016-05-24 21:05:01.511 设计模式之五原型模式[860:29812]内存地址:<Person:
0x100400380>
姓:张名:二性别:男地址:山东省

2016-05-24 21:05:01.511 设计模式之五原型模式[860:29812]内存地址:<Person:
0x1004003b0>
姓:张名:三性别:男地址:山东省

2016-05-24 21:05:01.512 设计模式之五原型模式[860:29812]内存地址:<Person:
0x1004003e0>
姓:张名:四性别:男地址:山东省

Program ended with exit code: 0
现在这个实例中只涉及了四个属性,偿若某一对象包含上百个属性之后,可想而知使用这种低质量代码的复杂程度,而使用原型模式之后,则变得相当轻松:

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person* per1 = [[Person alloc]initWithFirstName:@"张" andLastName:@"一" andSex:@"男" andAddress:@"山东省"];
Person* per2 = [per1 copy];
per2.lastName = @"二";
Person* per3 = [per1 copy];
per3.lastName = @"三";
Person* per4 = [per1 copy];
per4.lastName = @"四";
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per1,per1.firstName,per1.lastName,per1.sex,per1.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per2,per2.firstName,per2.lastName,per2.sex,per2.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per3,per3.firstName,per3.lastName,per3.sex,per3.address);
NSLog(@"内存地址:%@ 姓:%@ 名:%@ 性别:%@ 地址:%@",per4,per4.firstName,per4.lastName,per4.sex,per4.address);
}
return 0;
}


输出结果如下:

2016-05-24 22:08:59.949 设计模式之五原型模式[980:44674]内存地址:<Person:
0x100103a80>
姓:张名:一性别:男地址:山东省

2016-05-24 22:08:59.950 设计模式之五原型模式[980:44674]内存地址:<Person:
0x100105b90>
姓:张名:二性别:男地址:山东省

2016-05-24 22:08:59.950 设计模式之五原型模式[980:44674]内存地址:<Person:
0x100105bc0>
姓:张名:三性别:男地址:山东省

2016-05-24 22:08:59.950 设计模式之五原型模式[980:44674]内存地址:<Person:
0x100105bf0>
姓:张名:四性别:男地址:山东省

Program ended with exit code: 0
可以看到,两次输出结果除内存地址(内存地址由运行时系统自动分配)外,完全相同。且使用原型模式后,只需要根据现有对象进行copy,创建出一个新的对象,将新对象中个别不同于原对象的属性更改即可。
以上为我个人对原型模式的简单理解,如有不到之处,敬请指正。

未完待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: