iOS常用设计模式——原型模式
来源:互联网 发布:华为云计算论坛 编辑:程序博客网 时间:2024/05/01 18:19
原型模式的定义
原型模式(Prototype)即应用于“复制”操作的模式,此模式最初定义在《设计模式》(Addison-Wesley,1994),里面是这样定义的“使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象”。简单来理解就是根据这个原型创建新的对象,这种创建是指深复制,得到一份新的内存资源,而不是一个新的指针引用。使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象.
当一个类的组成比较复杂,例如包含多个组件或多个自定义类属性的时候,直接复制当前对象比从头开始创建对象要简单得多,则使用原型模式最为合适。又或者对象间的区别不大,只是几个属性不同的时候,也可以使用原型模式,前提是要继承同一个父类。
适用环境
需要创建的对象应独立于其类型与创建方式。
要实例化的类是在运行时决定的。
不想要与产品层次相对应的工厂层次。
不同类的实例间的差异仅是状态的若干组合。(复制相应数量的原型比手工实例化更加方便)
类不容易创建。(复制已有的组合对象并对副本进行修改会更容易)
主要涉及的知识:复制©
关于深复制与浅复制(深拷贝&浅拷贝),可以参考我博客里的一篇文章iOS中的深拷贝和浅拷贝的学习记录 这里就不过多介绍了.
我们来举一个例子,首先我们先创建一些假数据,让这些假数据看起来,很多,显得创建一个这样的item会比较难,通过这些假数据,加载到我们要操作的ViewControllview上面
创建假数据Person类
点h文件
// PersonItem.h// 原型模式CSDN//// Created by 王颜龙 on 13-12-30.// Copyright (c) 2013年 longyan. All rights reserved.//#import <Foundation/Foundation.h>@interface PersonItem : NSObject<NSCopying>@property (nonatomic, strong)UIImage *headerImg;//头像@property (nonatomic, assign)int age;//年纪@property (nonatomic, assign)CGFloat height;//身高@property (nonatomic, assign)CGFloat weight;//体重@property (nonatomic, assign)int numID;//学号@property (nonatomic, assign)int classNum;//学年@property (nonatomic, assign)int score1;//分数1@property (nonatomic, assign)int score2;//分数2@property (nonatomic, assign)int score3;//分数3@property (nonatomic, assign)int score4;//分数4@property (nonatomic, assign)int score0;//分数0@property (nonatomic, assign)BOOL isChoose;//判断是否被选中@end
加载假数据
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. NSMutableArray *arr = [[NSMutableArray alloc]initWithCapacity:0]; //制作假数据 for (int i = 0; i < 10; i++) { PersonItem *item = [[PersonItem alloc]init]; item.headerImg = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i+1]]; item.age = 15+i; item.height = 165+i; item.weight = 120+i; item.numID = 100+i; item.classNum = 10+i; item.score0 = 100+i; item.score1 = 90+i; item.score2 = 80+i; item.score3 = 70+i; item.score4 = 60+i; item.isChoose = NO; [arr addObject:item]; } EditViewController *vc = [[EditViewController alloc]initWithItem:arr]; UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc]; self.window.rootViewController = nav; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES;}
接下来,我们往项目里拖拽一个GMGridView,和一些图片数据,方便我们的展示
进入展示页面,是这样的
我们现在假设,如果我们想创建一个新的数据,但是这个数据又和之前的类似,但又有一些要修改的地方,例如我们修改头像,那么我们应该要怎么做呢? 我们可以像一开始那样重新创建一个preson类的item
PersonItem *item = [[PersonItem alloc]init]; item.headerImg = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i+1]]; item.age = 15+i; item.height = 165+i; item.weight = 120+i; item.numID = 100+i; item.classNum = 10+i; item.score0 = 100+i; item.score1 = 90+i; item.score2 = 80+i; item.score3 = 70+i; item.score4 = 60+i; item.isChoose = NO;
但是如果要是创建100个,1000个的话,实际上这样做是不太合理的,这个时候就要用到我们的原型模式了.
再次说一下原型模式的定义:当一个类的组成比较复杂,例如包含多个组件或多个自定义类属性的时候,直接复制当前对象比从头开始创建对象要简单得多,则使用原型模式最为合适。
在这里GMGridView的初始化以及一些修改 我就不写了,很简单,重点写一下3个按钮得方法
#pragma bottomView method//错误复制的方法- (void)errorItem{ if (self.chooseArr.count == 0) { return; } PersonItem *item = [self.chooseArr objectAtIndex:0]; item.headerImg = [UIImage imageNamed:@"15"]; [self.selectedItems addObject:item]; [self.gridView reloadData];}//正确复制的方法- (void)copyItem{ if (self.chooseArr.count == 0) { return; } PersonItem *itemNew = [[self.chooseArr objectAtIndex:0] copy]; itemNew.headerImg = [UIImage imageNamed:@"15"]; [self.selectedItems addObject:itemNew]; [self.gridView reloadData];}//删除按钮- (void)delItem{ if (self.chooseArr.count == 0) { return; } if (self.selectedItems.count <=1) { return; } [self.selectedItems removeObject:[self.chooseArr objectAtIndex:0]]; [self.chooseArr removeAllObjects]; [self.gridView reloadData];}
如果你点击了错误复制的方法,你会发现
你会发现什么,你复制了新的item,但是旧的item的头像也跟着改变了,这是为什么呢?我们看一下打印台
他们两个的内存地址是一样的,也就是说指针指向的是同一块内存地址,所以你修改了A,B自然也会变,也就是所谓浅拷贝.
这时如果你删除你会发现,他们都消失了
想避免这种方法的话,我们就要对person类实现深拷贝,那么就要遵循NSCopying协议,代码如下
#import "PersonItem.h"@implementation PersonItem//遵守NSCopying协议,深复制出一个新的item- (id)copyWithZone:(NSZone *)zone{ PersonItem *item = [[[self class]allocWithZone:zone]init]; item.headerImg = [_headerImg copy]; item.age = _age; item.height = _height; item.weight = _weight; item.numID = _numID; item.classNum = _classNum; item.score0 = _score0; item.score1 = _score1; item.score2 = _score2; item.score3 = _score3; item.score4 = _score4; return item;}@end
这样如果你选择正确的复制的话,结果就会是这样的
原因自然是他们分别是2个不同的内存地址,所以修改互不干扰
这就是我理解的原型模式,如有错误,希望大家指正.
- iOS常用设计模式——原型模式
- iOS常用设计模式——原型模式
- iOS常用设计模式——原型模式
- iOS设计模式—原型/外观
- 设计模式—原型模式
- 设计模式—原型模式
- 设计模式—原型模式
- 设计模式—原型模式
- Android常用设计模式——原型模式
- iOS设计模式-原型
- iOS 设计模式 - 原型模式
- iOS设计模式--原型模式
- 设计模式——原型设计模式
- 设计模式——原型设计模式
- 浅谈设计模式——原型模式
- 设计模式——原型模式(Prototype)
- 原型模式——设计模式系列
- 设计模式——原型模式
- IOS面试题归总
- 在resin4.0部署项目,出现server 'default' 错误
- html5位置定位
- 冒泡排序
- HDU 3572 Task Schedule(最大流Dinic算法)
- iOS常用设计模式——原型模式
- 字符串排列
- wamp 中添加虚拟主机
- iOS_UI_1_UIView
- 【JavaScript】DOM操作下拉框
- 数据库面试题
- 下载资源
- java异常处理——基础篇
- iOS学习总结之UI框架UI之文本输入控件( UITextField)