iOS 设计模式
很赞的总结
中文版
https://github.com/mobilefeng/BlueLibrary
==========MVC(model, view, controller)模式==========
1. model
Album:专辑数据
Album+TableRepresentation:扩展专辑数据,专门给UITableView展示用⭐️
2. view
AlbumView:专辑图片
HorizontalScroller:自定义的横滚视图 ⭐️
3. controller
ViewController
@interface ViewController () <UITableViewDataSource, UITableViewDelegate, HorizontalScrollerDelegate> {
// Model
NSArray *allAlbums;
NSDictionary *currentAlbumData;
NSInteger currentAlbumIndex;
// View
HorizontalScroller *scroller;
UITableView *dataTable;
}
- C管理着M和V,在C中有5个属性
= 在viewdidload中将两个view添加到C的self.view中
- C声明实现三个协议
= 将V的委托属性设置为C
= 在C中实现了协议中声明的方法
==========单例(Singleton)模式==========
官方定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
// LibraryAPI.h
+ (instancetype)sharedInstance; // LibraryAPI.m
+ (instancetype)sharedInstance {
static id _sharedInstance = nil;
static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{
_sharedInstance = [[LibraryAPI alloc] init];
}); return _sharedInstance;
} // ViewController
allAlbums = [[LibraryAPI sharedInstance] getAlbums];
1. 在.h中声明一个类方法,返回一个实例
2. 声明一个静态变量 _sharedInstance 保存类的实例
3. 声明一个静态变量 dispatch_once_t ,它确保初始化器代码只执行一次
4. 使用 GCD 执行初始化LibraryAPI变量的block,这正是单例模式的关键:一旦类已经被初始化,初始化器永远不会再被调用。
5. 调用时直接使用类方法
==========外观(Facade)模式==========
官方定义:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一系统更加容易使用
(比如把用户中心、商品中心、交易中心、检索、营销、客服统一起来,提供BNAPI接口,供APP调用,这就是活生生的外观模式)
外观模式,是将一些复杂的类封装起来提供单一接口
用 PersistencyManager 本地保存专辑数据,用 HTTPClient 处理远程连接
用 LibraryAPI 保存 PersistencyManager 和 HTTPClient 的实例,然后 LibraryAPI 将暴露一个简单的API去访问这些服务
@interface LibraryAPI (){
PersistencyManager *persistencyManager;
HTTPClient *httpClient;
BOOL isOnline;
}
==========装饰器(Decorator)模式==========
官方定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
在不修改原来代码的情况下动态的给对象增加新的行为和职责,它通过一个对象包装被装饰对象的方法来修改类的行为,这种方法可以做为子类化的一种替代方法
Category (类别)
在 Album 类基础上扩展出 Album+TableRepresentation 类
@interface Album (TableRepresentation) // tr is short for TableRepresentation
- (NSDictionary*)tr_tableRepresentation; @end
- 创建的方法
1. Command + N
2. 选择 iOS - Source - Objective-C File
3. File Type 选择 Category,Class 填基于的类名,File填扩展的名
- 特点
可以直接使用 Album的属性
==========适配器(Adapter)模式==========
官方定义:将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
在C++中用多重继承实现,但是OC是没有多重继承的,于是OC中是通过协议来实现
// ViewController.h
@interface ViewController : UIViewController // ViewController.m
@interface ViewController () <UITableViewDataSource, UITableViewDelegate, HorizontalScrollerDelegate> {
// ...
HorizontalScroller *scroller;
UITableView *dataTable;
}
一方面,ViewController 继承了 UIViewController
另一方面,为了能利用类 HorizontalScroller,将其方法封装成协议 HorizontalScrollerDelegate(也就是接口),供 ViewController 使用
Delegation (委托)
创建委托协议
1 @protocol HorizontalScrollerDelegate;
2
3 @interface HorizontalScroller : UIView
4
5 // weak 防止循环引用
6 // id 意味着 delegate 属性可以用任何遵从 HorizontalScrollerDelegate 的类赋值
7 @property (weak) id<HorizontalScrollerDelegate> delegate;
8 - (void)reload;
9
10 @end
11
12 // _____________________________________________________________________________________
13 //
14 @protocol HorizontalScrollerDelegate <NSObject>
15
16 @required
17 - (NSInteger)numberOfViewsForHorizontalScroller:(HorizontalScroller*)scroller;
18
19 - (UIView*)horizontalScroller:(HorizontalScroller*)scroller viewAtIndex:(int)index;
20
21 - (void)horizontalScroller:(HorizontalScroller*)scroller clickedViewAtIndex:(int)index;
22
23 @optional
24 - (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller*)scroller;
25
26 @end
主要分两块:
1. 14-26行是委托协议的声明,这里声明了一个名为 HorizontalScrollerDelegate 的委托协议,包含三个必须实现方法和一个可选实现方法
2. 第7行是给 HorizontalScroller 定义了一个实现 HorizontalScrollerDelegate 的属性 delegate
使用委托协议
1 // 1
2 @interface ViewController () <UITableViewDataSource, UITableViewDelegate, HorizontalScrollerDelegate> {
3 // ...
4 HorizontalScroller *scroller;
5 UITableView *dataTable;
6 }
7
8 // 2
9 - (void)viewDidLoad {
10 [super viewDidLoad];
11
12 // ...
13 scroller.delegate = self;
14 dataTable.delegate = self;
15 // ...
16 }
17
18 // 3
19 // 实现协议中声明的方法
主要分三块:
1. 第2行,在类的interface声明实现XX委托协议,4-5行,通常有实现相应协议对应的属性
2. 13-14行,将熟悉的delegate设置为类本身(self)
3. 19行,实现委托协议中声明的方法
如果一个协议包含的方法太多,可以考虑将其拆分,如:
UITableViewDataSource 和 UITableViewDelegate,前者负责数据源获取,后者负责对数据源进行加工细化
==========观察者(Observer)模式==========
官方定义:又叫发布-订阅(Publish/Subscribe)模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
这是一种松耦合的设计,在MVC中,当需要让模型对象和视图对象在不相互引用的情况下进行通信,就需要观察者模式。
Cocoa中有两种常见的观察者模式:通知(Notification)和KVO(Key-Value Observing)
通知(Notification)
// AlbumView.m
[[NSNotificationCenter defaultCenter] postNotificationName:@"BLDownloadImageNotification" object:self userInfo:@{@"imageView":coverImage, @"coverUrl":albumCover}]; // LibraryAPI.m
- (id)init {
if (self = [super init]) {
// ...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadImage:) name:@"BLDownloadImageNotification" object:nil];
} return self;
} - (void)downloadImage:(NSNotification *)notification {
UIImageView *imageView = notification.userInfo[@"imageView"];
NSString *coverUrl = notification.userInfo[@"coverUrl"];
// ...
} - (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
1. 第2行,发送名为BLDownloadImageNotification通知,其中userInfo会作为通知的一部分传递过去(15-16行)
2. 第8行,LibraryAPI 注册为 BLDownloadImageNotification 的观察者,当 AlbumView 发送通知时,系统会通知 LibraryAPI,LibraryAPI 调用 downloadImage: 来下载图片
3. 20-22行,观察者在销毁时,必须退订之前订阅的所有通知,否则一个通知发送给一个已经销毁的对象,会crash
KVO(Key-Value Observing)
它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。
// AlbumView.m
// 注册
[coverImage addObserver:self forKeyPath:@"image" options: context:nil];
// 实现回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"image"]) {
[indicator stopAnimating];
}
}
// 移除观察
- (void)dealloc {
[coverImage removeObserver:self forKeyPath:@"image"];
}
1. 注册通知
2. 实现回调方法
3. 移除观察(退订通知)
两点心得:
1. 通知是解决两个类间的消息传递,KVO是解决类内部属性间的消息传递
2. dealloc 中主要就是移除观察(退订通知)
==========观察者(Observer)模式==========
iOS 设计模式的更多相关文章
- IOS设计模式之一(MVC模式,单例模式)
iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...
- iOS 设计模式之工厂模式
iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...
- iOS设计模式之生成器
iOS设计模式之生成器 1.生成器模式的定义 (1): 将一个复杂的对象的构件与它的表示分离,使得相同的构建过程能够创建不同的表示 (2): 生成器模式除了客户之外还包括一个Director(指导者) ...
- IOS设计模式之三:MVC模式
IOS设计模式之三:MVC模式 模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团 ...
- iOS设计模式 - 享元
iOS设计模式 - 享元 原理图 说明 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分 ...
- iOS设计模式 - 责任链
iOS设计模式 - 责任链 原理图 说明 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链 ...
- iOS设计模式 - 模板
iOS设计模式 - 模板 原理图 说明 定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 源码 https://github.c ...
- iOS设计模式 - 访问者
iOS设计模式 - 访问者 原理图 说明 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 1.Visitor 抽象访问者角色,为该对象结构中具 ...
- iOS设计模式 - 迭代器
iOS设计模式 - 迭代器 原理图 说明 提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 源码 https://github.com/YouXianMing/iOS-Des ...
- iOS设计模式 - 中介者
iOS设计模式 - 中介者 原理图 说明 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 注:中介者对象本身没有复用价值 ...
随机推荐
- Unity3d的批渲染 batch rendering
http://blog.csdn.net/leonwei/article/details/41942157 批渲染(Batch) batch render 是大部分引擎提高渲染效率的方法,基本原理就是 ...
- 基于IDEA采用springboot+Mybatis搭建ssm框架简单demo项目的搭建配置流程
一.通过对比可以原始SSM搭建流程,spring boot省去了大量的配置,极大提高了开发者的效率.原始SSM框架搭建流程见博客: https://www.cnblogs.com/No2-explor ...
- Sql Server2008R2与IDEA的连接
数据库的连接笔者搞了一天,参阅了众多连接方案,大部分都是Eclipse和My sql,笔者一遍一遍的调试,终于皇天不负有心人,成绩先摆出来 为了让更多的新手能少走弯路,话不多说,上干货 首先,我们需要 ...
- 在虚拟机中设置NAT模式实现主机和虚拟机的通信
1.打开虚拟机,对几个节点进行网络连接的设置.虚拟机设置/网络连接,选择“NAT模式” 2.编辑—>虚拟网络编辑器来查看NAT模式中所用到的网段. 从上图可以看出,NAT中的子网IP是192.1 ...
- iOS开发 - 多线程实现方案之NSThread篇
NSThread API //类方法:创建一个线程 + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macos ...
- form表单提交转为ajax方式提交
<form action="xxx" method="get"> //action的值是请求的url地址 <div class="f ...
- 292. Nim游戏
292. Nim游戏 class Solution(object): def canWinNim(self, n): """ :type n: int :rtype: b ...
- Tinghua Data Mining 3
特征选择 男女身高 男女抽烟 先验分布 熵 衡量系统的不确定性 属性的价值 降低了不确定性 降低的幅度越高越好 主成分分析 旋转是的数据间的correlation消失掉 Q是正交阵 七长八短,长宽相关 ...
- tensorflow:实战Google深度学习框架第四章01损失函数
深度学习:两个重要特性:多层和非线性 线性模型:任意线性模型的组合都是线性模型,只通过线性变换任意层的全连接神经网络与单层神经网络没有区别. 激活函数:能够实现去线性化(神经元的输出通过一个非线性函数 ...
- iOS常用的存储方式
在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用的存储工具/方式: NSU ...