原型模式的解析-iOS

原型模式的解析-iOS

其他设计模式的介绍

1、简单工厂模式、工厂模式、抽象工厂模式的解析-iOS
2、建造者模式的解析-iOS
3、单例模式的解析-iOS
4、原型模式的解析-iOS

概率描述

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。百度百科

实用场景

“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。百度百科

在Objective-C中使用原型模式
在Objective-C中使用原型模式,就是说对对象的复制,就是我们常说的深拷贝和浅拷贝。在Cocoa Touch框架为NSObject的派生类提供了实现深拷贝的协议和相应的方法,NSCopying协议和-(id)copyWithZone:(NSZone )zone的方法。还有就是NSMutableCopying 和-(id)mutableCopyWithZone:(NSZone )zone的协议和方式。
也就是说如果要实现拷贝,就需要实现NSCopying协议和-(id)copyWithZone:(NSZone )zone的方法。如果是可变的要实现NSMutableCopying协议和-(id)copyWithZone:(NSZone )zone方法。

深拷贝、浅拷贝

浅拷贝:只是复制了指针的地址,并没有复制该指针指向的地址。

深拷贝:不但复制了指针的地址,还复制了指针地址指向的值。

代码解析:

-(void)shallowAndDeepCopy{
    /*******集合类的**********/
    //非可变集合
    NSDictionary *prototypeDic = @{@"A":@"1",@"B":@"2",@"C":@"3",@"D":@"4"};
    NSDictionary  *copyDicOne = prototypeDic.copy;
    NSDictionary  *copyDicTwo = prototypeDic.mutableCopy;

    NSLog(@"集合类的拷贝------------\n   prototypeDic的内容地址-%p \n copyDicOne-copy-的内容地址-%p  \n copyDicTwo-Mutable-的内容地址-%p  \n",prototypeDic,copyDicOne,copyDicTwo);
    NSLog(@"集合类的拷贝------------\n   prototypeDic的指针地址-%p \n copyDicOne-copy-的指针地址-%p   \n copyDicTwo-Mutable-的指针地址-%p  \n",&prototypeDic,&copyDicOne,&copyDicTwo);

    //可变集合
    NSMutableDictionary *prototypeMutableDic =[[NSMutableDictionary alloc]initWithObjectsAndKeys:@"A",@"1",@"B",@"2",@"C",@"3",@"D",@"4", nil ];
    NSMutableDictionary  *copyMutaleDicOne = prototypeMutableDic.copy;
    NSMutableDictionary  *copyMutaleDicTwo = prototypeMutableDic.mutableCopy;

    NSLog(@"可变集合类的拷贝------------\n   prototypeMutableDic的内容地址-%p \n copyMutaleDicOne-copy-的内容地址-%p \n copyMutaleDicTwo-Mutable-的内容地址-%p  \n",prototypeMutableDic,copyMutaleDicOne,copyMutaleDicTwo);
    NSLog(@"可变集合类的拷贝------------\n   prototypeMutableDic的指针地址-%p \n copyMutaleDicOne-copy-的指针地址-%p \n copyMutaleDicTwo-Mutable-的指针地址-%p  \n",&prototypeMutableDic,&copyMutaleDicOne,&copyMutaleDicTwo);


    /**********非集合类的**********/
    //不可变的
    NSString *prototypeStr = @"猪猪侠";
    NSString *copyStrOne = prototypeStr.copy;
    NSString *copyStrTwo = prototypeStr.mutableCopy;

    NSLog(@"非集合类的拷贝------------\n   prototypeStr的内容地址-%p \n copyStrOne-copy-的内容地址-%p  \n copyStrTwo-Mutable-的内容地址-%p \n",prototypeStr,copyStrOne,copyStrTwo);
    NSLog(@"非集合类的拷贝------------\n   prototypeStr的指针地址-%p \n copyStrOne-copy-的指针地址-%p  \n copyStrTwo-Mutable-的指针地址-%p \n",&prototypeStr,&copyStrOne,&copyStrTwo);

    //可变的
    NSMutableString *prototypeMutableStr = [[NSMutableString alloc]initWithString:@"小猪佩奇"];
    NSMutableString *copyMutabelStrOne = prototypeMutableStr.copy;
    NSMutableString *copyMutabelStrTwo = prototypeMutableStr.mutableCopy;
    NSLog(@"可变非集合类的拷贝------------\n   prototypeMutableStr的内容地址-%p \n copyMutabelStrOne-copy-的内容地址-%p   \n  copyMutabelStrTwo-Mutable-的内容地址-%p \n",prototypeMutableStr,copyMutabelStrOne,copyMutabelStrTwo);
    NSLog(@"可变非集合类的拷贝------------\n   prototypeMutableStr的指针地址-%p \n copyMutabelStrOne-copy-的指针地址-%p   \n  copyMutabelStrTwo-Mutable-的指针地址-%p \n",&prototypeMutableStr,&copyMutabelStrOne,&copyMutabelStrTwo);

}

打印的结果

2018-06-12 15:04:35.457387+0800 DesignDemo[17492:692166] 集合类的拷贝------------
   prototypeDic的内容地址-0x6000000f2100 
 copyDicOne-copy-的内容地址-0x6000000f2100  
 copyDicTwo-Mutable-的内容地址-0x60000023e540  

2018-06-12 15:04:35.457509+0800 DesignDemo[17492:692166] 集合类的拷贝------------
   prototypeDic的指针地址-0x7ffeecd84988 
 copyDicOne-copy-的指针地址-0x7ffeecd84980   
 copyDicTwo-Mutable-的指针地址-0x7ffeecd84978  

2018-06-12 15:04:35.457617+0800 DesignDemo[17492:692166] 可变集合类的拷贝------------
   prototypeMutableDic的内容地址-0x60000023ce40 
 copyMutaleDicOne-copy-的内容地址-0x60000023d2c0 
 copyMutaleDicTwo-Mutable-的内容地址-0x600000420160  

2018-06-12 15:04:35.457896+0800 DesignDemo[17492:692166] 可变集合类的拷贝------------
   prototypeMutableDic的指针地址-0x7ffeecd84970 
 copyMutaleDicOne-copy-的指针地址-0x7ffeecd84968 
 copyMutaleDicTwo-Mutable-的指针地址-0x7ffeecd84960  

2018-06-12 15:04:35.458083+0800 DesignDemo[17492:692166] 非集合类的拷贝------------
   prototypeStr的内容地址-0x102e7c4d8 
 copyStrOne-copy-的内容地址-0x102e7c4d8  
 copyStrTwo-Mutable-的内容地址-0x604000442580 

2018-06-12 15:04:35.458478+0800 DesignDemo[17492:692166] 非集合类的拷贝------------
   prototypeStr的指针地址-0x7ffeecd84958 
 copyStrOne-copy-的指针地址-0x7ffeecd84950  
 copyStrTwo-Mutable-的指针地址-0x7ffeecd84948 

2018-06-12 15:04:35.458711+0800 DesignDemo[17492:692166] 可变非集合类的拷贝------------
   prototypeMutableStr的内容地址-0x600000257df0 
 copyMutabelStrOne-copy-的内容地址-0x60000023d440   
  copyMutabelStrTwo-Mutable-的内容地址-0x600000257c10 

2018-06-12 15:04:35.459056+0800 DesignDemo[17492:692166] 可变非集合类的拷贝------------
   prototypeMutableStr的指针地址-0x7ffeecd84940 
 copyMutabelStrOne-copy-的指针地址-0x7ffeecd84938   
  copyMutabelStrTwo-Mutable-的指针地址-0x7ffeecd84930 

从上面的结果我们可以知道:
1、非集合类
不可变非集合类的对象copy: 指针拷贝,共同内存
不可变的非集合类的对象mutableCopy:是对内容的的拷贝,创建了新的内存空间。
可变的非集合类的对象copy:是对内容的拷贝,创建的新的内存空间
可变的非集合类的对象mutableCopy:是对内容的拷贝,创建的新的内存空间
2、集合类的
不可变集合类的对象copy: 指针拷贝,共同内存
不可变的集合类的对象mutableCopy:是对内容的的拷贝,创建了新的内存空间。
可变的集合类的对象copy:是对内容的拷贝,创建的新的内存空间
可变的集合类的对象mutableCopy:是对内容的拷贝,创建的新的内存空间

案例解析

我们先来分析一下,比如:小明喜欢看书,就买了一本《小王子》的书。
代码如下:
人物类的代码

#import "PrototypePerson.h"
@interface PrototypePerson ()
@property(nonatomic,strong)NSMutableArray *bookArray;
@property(nonatomic,copy)NSString *name;
/*
 *init方法
 */
- (instancetype)initWithName:(NSString *)name;
/*
 *添加书
 */
-(void)addBook:(NSString *)bookName;

@end

@implementation PrototypePerson
- (instancetype)initWithName:(NSString *)name
{
    self = [super init];
    if (self) {
        _name = name;
        _bookArray = [[NSMutableArray alloc] initWithCapacity:20];

    }
    return self;
}

-(void)addBook:(NSString *)bookName{
    [_bookArray addObject:bookName];
}

@end

小明买书的代码

    //原型模式
    //平常模式
    PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
    //小明买了本《小王子》的书
    [prototypePersonOne addBook:@"《小王子》"];

    //现在小黄,也买了一个书柜,也买了本《小王子》的书
    PrototypePerson *prototypePersonTwo = [[PrototypePerson alloc]initWithName:@"小黄"];
    [prototypePersonTwo addBook:@"《小王子》"];

然后小黄发现小明这本书很好,他就买了一本一摸一样的书。
代码如下

    PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
    //小明买了本《小王子》的书
    [prototypePersonOne addBook:@"《小王子》"];

    //现在小黄,也买了一个书柜,也买了本《小王子》的书
    PrototypePerson *prototypePersonTwo = [[PrototypePerson alloc]initWithName:@"小黄"];
    [prototypePersonTwo addBook:@"《小王子》"];

现在小明只有一本书,我们就只要添加一本书就行,如果过段时间小明有几百本书,这个时候小黄根据小明的书籍买了一摸一样的书籍,这个时候,我们还需要一本一本的书籍添加吗?
这个时候原型模式就派上用场了。我们可以在我们人物类上面实现NSCopying协议,实现- (id)copyWithZone:(NSZone *)zone方法,这样就实现了小明这个人物的深拷贝。
代码如下:
人物类的代码:


#import "PrototypePerson.h"
@interface PrototypePerson ()<NSCopying>
@property(nonatomic,strong)NSMutableArray *bookArray;
@property(nonatomic,copy)NSString *name;
/*
 *init方法
 */
- (instancetype)initWithName:(NSString *)name;
/*
 *添加书
 */
-(void)addBook:(NSString *)bookName;

@end

@implementation PrototypePerson
- (instancetype)initWithName:(NSString *)name
{
    self = [super init];
    if (self) {
        _name = name;
        _bookArray = [[NSMutableArray alloc] initWithCapacity:20];

    }
    return self;
}

-(void)addBook:(NSString *)bookName{
    [_bookArray addObject:bookName];
}

-(id)copyWithZone:(NSZone *)zone{
    PrototypePerson *prototypePerson = [[[self class] allocWithZone:zone]initWithName:_name];
    prototypePerson.bookArray = [_bookArray mutableCopy];
    return prototypePerson;

}
@end

//对小明人物类的深拷贝

    //原型模式

    PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
    //小明买了本《小王子》的书
    [prototypePersonOne addBook:@"《小王子》"];


    //如果,以后小明买了很多本书,过了一段时间,小黄,和他买了一摸一样的书籍,这个时候就可以使用原型模式,实现NSCopying协议,实现- (id)copyWithZone:(NSZone *)zone方法来实现对象的拷贝。
    //小黄
    PrototypePerson *prototypePersonThree =[prototypePersonOne copy];
//小黄发现了一本很好的书
    [prototypePersonThree addBook:@"《睡前故事》"];

    NSLog(@"小明内存地址 ---- %p \n 小黄内存地址 -----%p",prototypePersonOne,prototypePersonThree);

我们来打印一下,小明和小黄的内存地址和购买的书籍数据

2018-06-12 16:36:49.541459+0800 DesignDemo[19613:790893] 小明内存地址 ---- 0x600000237700 
 小黄内存地址 -----0x6000002373e0
2018-06-12 16:36:49.541741+0800 DesignDemo[19613:790893] 小明的书籍 ---- (
    "\U300a\U5c0f\U738b\U5b50\U300b"
) 
 小黄内存书籍 -----(
    "\U300a\U5c0f\U738b\U5b50\U300b",
    "\U300a\U7761\U524d\U6545\U4e8b\U300b"
)

根据上面的结果,我们发现小明和小黄的内存地址不一样,说明实现了深拷贝,小明和小黄豆是购买了《小王子》这本书籍,小黄还买了本《睡前故事》。

总结

如果有写的不正确或者侵权的,希望大家给我提出来,我会及时修改。谢谢大家。

猜你喜欢

转载自blog.csdn.net/u014644610/article/details/80668017