Cowboy Tech

iOS设计模式-原型

原型模式解决的问题

每个对象需要重新创建

StudentModel *stu1 = [[StudentModel alloc] init];
stu1.name          = @"小王";
stu1.age           = @(19);
stu1.address       = @"中关村";
stu1.totalScore    = @(100);


StudentModel *stu2 = [[StudentModel alloc] init];
stu1.name          = @"小刘";
stu1.age           = @(19);
stu1.address       = @"中关村";
stu1.totalScore    = @(100);

原型设计:自我拷贝

使用场景:对象创建特别复杂,两个对象在抽象逻辑完全一致,只是在实例化的细节略有差异,如果要重新创建一个对象,不如拷贝自己再去修改

ProtoypeCopyProtocol

@protocol ProtoypeCopyProtocol <NSObject>
@required
- (id)clone;
@end

StudentModel

@interface StudentModel : NSObject <ProtoypeCopyProtocol>

@property (nonatomic, strong) NSString  *name;
@property (nonatomic, strong) NSNumber  *age;
@property (nonatomic, strong) NSString  *address;
@property (nonatomic, strong) NSNumber  *totalScore;

- (id)clone;
@end

@implementation StudentModel

- (id)clone {

    StudentModel *student = [[[self class] alloc] init];

    // 完成复杂操作的所有作业
    student.name       = self.name;
    student.age        = self.age;
    student.address    = self.address;
    student.totalScore = self.totalScore;
    return student;
}
@end

viewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 学生1
    StudentModel *stu1 = [[StudentModel alloc] init];
    stu1.name          = @"小王";
    stu1.age           = @(19);
    stu1.address       = @"中关村";
    stu1.totalScore    = @(100);

    // 学生2
    StudentModel *stu2 = [stu1 clone];
    stu2.name          = @"小红";
}

框架级别的原型模式:NSCopying

BasCopyObject

//遵循NSCopying协议
@interface BasCopyObject : NSObject <NSCopying>


//子类不要重载这个方法
- (id)copyWithZone:(NSZone *)zone {
    .........
BasCopyObject *copyObject = [[self class] allocWithZone:zone];

// 赋值操作作业,//由子类重载实现
[self copyOperationWithObject:copyObject];
return copyObject;
}

- (void)copyOperationWithObject:(id)object {

}

StudentModel

//继承基类
@interface StudentModel : BasCopyObject

- (void)copyOperationWithObject:(StudentModel *)object {  
object.name = self.name;
object.age  = self.age;
}

ViewController

StudentModel *stu1 = [[StudentModel alloc] init];
StudentModel *stu2 = stu1.copy;

深拷贝与浅拷贝

浅拷贝

ClassModel

- (void)copyOperationWithObject:(ClassModel *)object {
object.className = self.className;
object.students = self.students;
}

ViewController

ClassModel *class1 = [[ClassModel alloc] init];
class1.className   = @"班级1";
class1.students    = @[stu1, stu2];

ClassModel *class2 = class1.copy;

这样拷贝出来的数组students内存地址一样。说明数组拷贝没有成功。就好像student既属于A班,又属于B班

深拷贝

同时要求数组里的每个对象也要实现NSCopying协议

ClassModel

- (void)copyOperationWithObject:(ClassModel *)object {

    object.className = self.className;
    // 完成了深拷贝(完整的复制了集合里面的对象)
    object.students  = [[NSArray alloc] initWithArray:self.students copyItems:YES];
}

ViewController

ClassModel *class1 = [[ClassModel alloc] init];
class1.className   = @"班级1";
class1.students    = @[stu1, stu2];

ClassModel *class2 = class1.copy;    

这样拷贝出来的class2中的数组对象students才能与class1中的数组对象students有不同的内存地址

[self class]

这里使用self,是因为StudentModel可能会被子类继承

StudentModel *student = [[[self class] alloc] init];