iOS设计模式—原型/外观

原型设计模式

首先从简单的入手。看看原型模式吧。学习Javascript的时候有一个ProtoType 翻译过来就是原型,那么什么是原型呢?

举个生活中的例子,假设你要做生意 要发名片 那么 你就需要先设计一个名片然后打印N多份然后发送给客户。即copy。

在编程语言当中,经常有这样的情况,如我想操作某个对象,但是我又不想把他的内容改变了,这时候需要先保存这个对象。或者是我需要多个一样的对象。

模板的用处

  • 为什么要制作模板?
    因为我们要制作一系列的东西,他们都有相同之处,我们只需要修改其中一个模板的某些元素,就能供其他使用,这就是模板
    抽象的部分一致,细节不同。

    原型模式的基本原理


Paste_Image.png


拷贝自己

  • 何时使用原型模式
    1:某些对象或控件特别复杂,我们直接重写的话比较麻烦,而直接从之前的模板中拷贝出来,只需修改其中的几个元素就能使用
  • 使用
    1:定义一个协议
#import <Foundation/Foundation.h>

@protocol ProtoypeCopyProtocol <NSObject>

@required

// 返回自己的一个拷贝样本
- (id)clone;

@end

2:遵守协议,并实现拷贝方法

#import <Foundation/Foundation.h>
#import "ProtoypeCopyProtocol.h"

@interface Student : NSObject<ProtoypeCopyProtocol>

@property(nonatomic, copy) NSString * name;
@property(nonatomic, assign) NSInteger  age;
@property(nonatomic, copy) NSString * address;
@property(nonatomic, assign) NSInteger  totalScore;

- (id)clone;    // 实现复制方法

@end

m文件

#import "Student.h"

@implementation Student

/**
 *  完成复制的所有操作
 *
 *  @return 学生对象
 */
- (id)clone{

    Student *student = [[[self class] alloc] init];
    student.name = self.name;
    student.age = self.age;
    student.address = self.address;
    student.totalScore = self.totalScore;

    return student;
}

@end
  • 在主控制器中调用复制的方法
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    Student *student = [[Student alloc] init];
    student.name = @"贾元发";
    student.age = 24;
    student.address = @"浙江中小企业大厦";
    student.totalScore = 100;

    Student *student2 = [student clone];
    NSLog(@"%@", student2.name);
}
  • 以上只是通过一个小的模型来展示了原型模式的实现原理,如果一个对象很简单,属性很少,我们会觉得并没有什么卵用,但是如果很复杂的一个控件有很多相似之处,使用原型模式设计是不是让我们开发事半功倍?
NSCopying 协议的使用细节
  • NSCopying协议的使用
  • 深拷贝与浅拷贝
  • 不支持NSCopying协议的对象

  • NSCopying协议的使用
    1:创建基类,遵守NSCopying协议,并实现协议的代理方法

#import <Foundation/Foundation.h>

@interface BaseCopyObject : NSObject<NSCopying>

/**
 *  == 子类不要重载 ==
 *
 *  @return 复制的对象
 */
- (id)copyWithZone:(NSZone *)zone;

/**
 *  == 由子类重载实现,只是为了通过这个方法让外界拿到拷贝过的对象用来进行进一步的赋值 =
 *
 * 复制(赋值实现)
 *  @param object 已经复制的对象
 */
- (void)copyOperationObject:(id)object;

@end

.m方法

#import "BaseCopyObject.h"

@implementation BaseCopyObject

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

    BaseCopyObject *copyObject = [[self class] allocWithZone:zone];

    // 赋值操作作业
    [self copyOperationObject:copyObject];

    return copyObject;
}

- (void)copyOperationObject:(id)object{
    // 空实现、什么操作都不做
}

@end

2:Model类继承自实现了NSCopying协议的类

#import "BaseCopyObject.h"

@interface StudentModel : BaseCopyObject

@property(nonatomic, copy) NSString * name;
@property(nonatomic, assign) NSInteger  age;

@end

实现其协议方法

#import "StudentModel.h"

@implementation StudentModel

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

@end

主类中调用:

StudentModel *studentModel = [[StudentModel alloc] init];
    studentModel.name = @"贾元发";

    StudentModel *stu2 = studentModel.copy;
    NSLog(@"%@", studentModel.name);
    NSLog(@"%@%@", studentModel, stu2);

深拷贝与浅拷贝

  • 写一个Class对象,同样继承实现了NSCopying协议的基类
#import "BaseCopyObject.h"

@interface ClassModel : BaseCopyObject

@property(nonatomic, copy) NSString * className;
@property (nonatomic, strong) NSArray *students;

@end

m.

#import "ClassModel.h"

@implementation ClassModel

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

    object.className = self.className;
    object.students = self.students;
}

@end
  • 调用以及打印结果:
ClassModel *classModel = [[ClassModel alloc] init];
    classModel.className = @"班级一";
    classModel.students = @[studentModel, stu2];

    ClassModel *classModel2 = classModel.copy;
    NSLog(@"%@%@", classModel.students, classModel2.students);

Paste_Image.png

如何实现深拷贝?我们在赋值的时候使用深拷贝的方法即可:

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

    object.className = self.className;

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

Paste_Image.png

所以,在我们使用NSCopying在对对象进行拷贝的时候,如果对象中包含数组、集合、字典的时候一定要使用initWithArray: copyItem方法进行深拷贝。要注意的是数组、集合、字典里面的对象也要实现NSCopying协议。

如何去一个指定的地方
  • 自驾或者坐火车(限制条件:地图、住宿)
  • 用不同的手段达到相同的目的
外观模式的原理

Paste_Image.png
  • 外观模式的基本原理
    1:不关心内容实现,只用来使用
    2:何时使用外观模式
  • 为什么使用?
    1:解耦合(只提供几个简单的接口)
    2:简化了操作,将繁琐的实现过程封装,使用者不需要关心实现。
如何绘制复杂的图形
  • 为何要简化操作逻辑
  • 用外观模式简化流程
  • 可维护性探讨

  • 绘制一个圆,绘制一个矩形,两者结合起来的方法

  • Shape类

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface Shape : NSObject

- (void)draw;

@end
  • 绘制圆的类
#import "Shape.h"

@interface Circle : Shape

@property (nonatomic) CGFloat radius;

- (void)draw;

@end
  • 绘制矩形类
#import "Shape.h"

@interface Rectangle : Shape

@property (nonatomic) CGFloat width;
@property (nonatomic) CGFloat height;

- (void)draw;

@end
  • 图形创造器类
/*
 图形创造器
 */
#import <Foundation/Foundation.h>
#import "Circle.h"
#import "Rectangle.h"

@interface ShapeMaker : NSObject

+ (void)drawCircleWithParas:(NSDictionary *)paras;

+ (void)drawCircleAndRectangle:(NSDictionary *)paras;

@end
  • 主控制器调用
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 绘制一个圆
    [ShapeMaker drawCircleWithParas:@{@"radius": @"10"}];

    // 绘制圆 + 矩形
    [ShapeMaker drawCircleAndRectangle:@{@"a": @"2"}];


    // 绘制一个圆
    Circle *circle = [Circle new];
    circle.radius = 10.0f;
    [circle draw];

    // 绘制一个矩形
    Rectangle *restangle = [Rectangle new];
    restangle.width = 10.0f;
    restangle.height = 20.0f;
    [restangle draw];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
  • 以上通过对绘制图像方法的整合,解决了如何绘制复杂图形的问题,这就是外观模式


文/Jafar(简书作者)
原文链接:http://www.jianshu.com/p/9690aba7ff14
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值