1.代理模式
代理模式完成委托方交給的任務(wù),委托方有一些任務(wù)自己不想完成,但是還需要要實(shí)現(xiàn),則將該任務(wù)存放到協(xié)議中,由代理完成.但是代理并不會主動的執(zhí)行任務(wù),需要委托方通知代理飞蹂。
1.1應(yīng)用場景
當(dāng)一個(gè)類的某些功能需要由別的類來實(shí)現(xiàn)茧跋,但是又不確定具體會是哪個(gè)類實(shí)現(xiàn)磕蛇。1.2優(yōu)勢
解耦合1.3敏捷原則
開放-封閉原則1.4實(shí)例
tableview的 數(shù)據(jù)源delegate握联,通過和protocol的配合谐丢,完成委托訴求拳球。列表row個(gè)數(shù)delegate舀瓢,自定義的delegate滞乙。
/*實(shí)現(xiàn)
說明:代理是一對一的,響應(yīng)棧內(nèi)最近一個(gè)代理對象(多為傳值,相連的頁面)
代理的使用债蓝,可以簡單的概括為兩個(gè)三步走壳鹤,即創(chuàng)建代理的三步和使用代理的三步。
1.創(chuàng)建代理:
2.創(chuàng)建代理協(xié)議
3.聲明代理方法
4.聲明代理屬性
5.使用代理:
6.遵守代理協(xié)議
7.設(shè)置代理對象
8.實(shí)現(xiàn)代理方法
代碼實(shí)現(xiàn):下面我們直接上代碼饰迹,實(shí)現(xiàn)點(diǎn)擊代理按鈕芳誓,上面的label顯示“代理傳的值”*/
//創(chuàng)建代理(傳值的頁面)
//.h文件中
#import <UIKit/UIKit.h>
//創(chuàng)建代理協(xié)議
@protocol RYTestDelegate <NSObject>
//聲明代理方法
@optional
- (void)delegateTestName:(NSString *)name;
@end
@interface RYDelegateSecondViewController : UIViewController
聲明代理屬性
@property (nonatomic, weak) id<RYTestDelegate> delegate;
@end
//.m文件中
-(void)clickedDeleBtn{
NSLog(@"代理");
//要傳遞的對象
NSString *myText = @"代理傳的值";
if ([self.delegate respondsToSelector:@selector(delegateTestName:)]) {
[self.delegate delegateTestName:myText];
}
}
————————————————
//2.使用代理(接收值的頁面)
#import "RYDelegateSecondViewController.h" //創(chuàng)建了代理的頁面
@interface RYDelegateViewController ()<RYTestDelegate>
@property(nonatomic ,strong) UILabel *textLabel;
@end
-(void)clickedNextBtn{
RYDelegateSecondViewController *vc = [[RYDelegateSecondViewController alloc]init];
vc.delegate = self;
[self.navigationController pushViewController:vc animated:YES];
}
-(void)delegateTestName:(NSString *)name{
self.textLabel.text = name;
NSLog(@"傳值回來====>>代理");
}
————————————————
2. 觀察者模式(通知機(jī)制,KVO機(jī)制)
觀察者模式本質(zhì)上是一種發(fā)布-訂閱模型,用以消除具有不同行為的對象之間的耦合,通過這一模式啊鸭,不同對象可以協(xié)同工作锹淌,同時(shí)它們也可以被復(fù)用于其他地方Observer從Subject訂閱通知,ConcreteObserver實(shí)現(xiàn)重現(xiàn)ObServer并將其重載其update方法赠制。
- 2.1應(yīng)用場景
一般為model層對赂摆,controller和view進(jìn)行的通知方式,不關(guān)心誰去接收,只負(fù)責(zé)發(fā)布信息烟号。 - 2.2優(yōu)勢
解耦合 - 2.3敏捷原則
接口隔離原則,開放-封閉原則 - 2.4實(shí)例
Notification通知中心汪拥,注冊通知中心达传,任何位置可以發(fā)送消息,注冊觀察者的對象可以接收喷楣。
/*實(shí)現(xiàn)
說明:觀察者模式定義了一種一對多的依賴關(guān)系趟大,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象鹤树。這個(gè)主題對象在狀態(tài)上發(fā)生變化時(shí)铣焊,會通知所有觀察者對象,使它們能夠自動更新自己罕伯。 簡而言之曲伊,就是A和B,A對B的變化感興趣追他,就注冊A為觀察者坟募,當(dāng)B發(fā)生變化時(shí)通知A,告知B發(fā)生了變化邑狸。這個(gè)也叫做經(jīng)典觀察者模式懈糯。*/
————————————————
//1.通知機(jī)制
//注冊通知接收者的代碼(A):
//注冊通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registerCompletion:)
name:@"RegisterCompeletionNotification"
object:nil];
-(void)registerCompletion:(NSNotification *)notification{
NSDictionary *theData = notification.userInfo;
NSString *username = [theData objectForKey:@"username"];
NSLog(@"username = %@",username);
}
————————————————
//投送通知的代碼
-(void)clickedNotifitionCenterBtn{
NSLog(@"通知");
NSDictionary *dataDic = [NSDictionary dictionaryWithObject:@"通知值" forKey:@"username"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"RegisterCompeletionNotification"
object:nil
userInfo:dataDic];
}
————————————————
/*問題1. object是干嘛的?是不是可以用來傳值?
答:object是用來過濾Notification的,只接收指定的sender所發(fā)的Notification…傳值請用userInfo,而不是object
問題2. iOS中,廣播通知(broadcast notification)/本地通知(local notification)/推送通知(push notification)有什么區(qū)別和不同?
出了名字相似以外,廣播通知和其他兩個(gè)通知是完全不一樣的: 廣播通知是cocoatouch中觀察者模式的一種機(jī)制, 實(shí)現(xiàn)應(yīng)用內(nèi)部多個(gè)對象的通信…本地通知和推送通知中的"通知"是一種"提示"…通過警告框,發(fā)出聲音,振動和在應(yīng)用圖標(biāo)上顯示數(shù)組等,在計(jì)劃時(shí)間到達(dá)時(shí),本地通知通過本地iOS發(fā)出,推送通知由第三方程序發(fā)送給蘋果遠(yuǎn)程服務(wù)器,再由遠(yuǎn)程服務(wù)器推送給iOS特定應(yīng)用.
————————————————
*/
3.單例模式
單例模式可以保證App在程序運(yùn)行中,一個(gè)類只有唯一個(gè)實(shí)例单雾,從而做到節(jié)約內(nèi)存赚哗。
在整個(gè)App程序中,這一份資源是共享的硅堆。
提供一個(gè)固定的實(shí)例創(chuàng)建方法屿储。
- 3.1應(yīng)用場景
確保程序運(yùn)行期某個(gè)類,只有一份實(shí)例渐逃,用于進(jìn)行資源共享控制够掠。 - 3.2優(yōu)勢
使用簡單,延時(shí)求值茄菊,易于跨模塊 - 3.3敏捷原則
單一職責(zé)原則 - 3.4實(shí)例
[UIApplication sharedApplication]疯潭。 - 3.5注意事項(xiàng)
確保使用者只能通過 getInstance方法才能獲得,單例類的唯一實(shí)例面殖。
java袁勺,C++中使其沒有公有構(gòu)造函數(shù),私有化并覆蓋其構(gòu)造函數(shù)畜普。
object c中期丰,重寫allocWithZone方法,保證即使用戶用 alloc方法直接創(chuàng)建單例類的實(shí)例,返回的也只是此單例類的唯一靜態(tài)變量钝荡。
//實(shí)現(xiàn)
/*一個(gè)單例類,保證一個(gè)類僅有一個(gè)實(shí)例街立,在整個(gè)程序中只有一個(gè)實(shí)例,并且提供一個(gè)類方法供全局調(diào)用埠通,在編譯時(shí)初始化這個(gè)類赎离,然后一直保存在內(nèi)存中,到程序(APP)退出時(shí)由系統(tǒng)自動釋放這部分內(nèi)存端辱。
在整個(gè)應(yīng)用程序中梁剔,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化1次),一般用于工具類舞蔽。例如:登陸控制器荣病,網(wǎng)絡(luò)數(shù)據(jù)請求,音樂播放器等一個(gè)工程需要使用多次的控制器或方法渗柿。
如工具類个盆、公共跳轉(zhuǎn)類等經(jīng)常調(diào)用的類,都會采用單例模式朵栖。*/
static LoginViewController * _instance = nil;
+(instancetype)sharedLoginHandle{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// loginVC = [[LoginViewController alloc] init];
_instance= [[self alloc] init];
});
return _instance;
}
————————————————
4.策略模式
策略模式定義了一系列的算法颊亮,并將每一個(gè)算法封裝起來,而且使它們還可以相互替換陨溅。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化终惑。
- 4.1應(yīng)用場景
定義算法族,封裝起來门扇,使他們之間可以相互替換雹有。 - 4.2優(yōu)勢
使算法的變化獨(dú)立于使用算法的用戶 - 4.3敏捷原則
接口隔離原則;
多用組合悯嗓,少用繼承件舵;
針對接口編程,而非實(shí)現(xiàn)脯厨。 - 4.4實(shí)例
排序算法铅祸,NSArray的sortedArrayUsingSelector;經(jīng)典的鴨子會叫合武,會飛案例临梗。 - 4.5注意事項(xiàng)
1、剝離類中易于變化的行為稼跳,通過組合的方式嵌入抽象基類
2盟庞、變化的行為抽象基類為,所有可變變化的父類
3汤善、用戶類的最終實(shí)例什猖,通過注入行為實(shí)例的方式票彪,設(shè)定易變行為
防止了繼承行為方式,導(dǎo)致無關(guān)行為污染子類不狮。完成了策略封裝和可替換性降铸。
//實(shí)現(xiàn)
/*策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來摇零,而且使它們還可以相互替換推掸。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。
簡而言之就是把控制其中的一大串 if...else... 或者 switch()單獨(dú)抽出來寫成一些列的算法文件, 減輕了ViewController的負(fù)擔(dān)同時(shí)也簡化操作驻仅,提高代碼維護(hù)性谅畅。算法可以自由切換,避免使用多重條件判斷噪服,擴(kuò)展性良好抵栈。
如果一個(gè)系統(tǒng)的策略多于四個(gè)趁耗,就需要考慮使用混合模式掌眠,解決策略類膨脹的問題胡野。*/
————————————————
//在UITextField的子類CustomField中
#import <UIKit/UIKit.h>
#import "InputValidator.h"
@interface CustomField : UITextField
//抽象的策略
@property (nonatomic, strong) InputValidator *validator;
/**
初始化textField
@param frame frame
@return 實(shí)例對象
*/
- (instancetype)initWithFrame:(CGRect)frame;
/**
驗(yàn)證輸入合法性
@return 是否合法,不合法,讀取InputValidator當(dāng)中的errorMessage
*/
- (BOOL)validate;
@end
//.m
- (BOOL)validate {
return [self.validator validateInput:self];
}
————————————————
//創(chuàng)建一個(gè)驗(yàn)證策略的基類 InputValidator
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface InputValidator : NSObject
/**
策略的輸入
@param input input
@return 如果為YES,表示測試通過,如果為NO,表示測試不通過
*/
- (BOOL)validateInput:(UITextField *)input;
//當(dāng)validateInput為NO的時(shí)候,我們來讀取errorMessage
@property (nonatomic, strong) NSString *errorMessage;
@end
#import "InputValidator.h"
@implementation InputValidator
- (BOOL)validateInput:(UITextField *)input {
return NO;
}
@end
————————————————
//創(chuàng)建 一個(gè)郵箱驗(yàn)證方法類EmailValidator,繼承于驗(yàn)證策略的基類(InputValidator)
//然后重寫輸入驗(yàn)證的驗(yàn)證方法
#import "EmailValidator.h"
@implementation EmailValidator
- (BOOL)validateInput:(UITextField *)input {
if (input.text.length <= 0) {
self.errorMessage = @"郵箱沒有輸入";
}
else{
self.errorMessage = nil;
}
return self.errorMessage == nil ? YES : NO;
}
@end
————————————————
//創(chuàng)建 一個(gè)手機(jī)驗(yàn)證方法類PhoneNumberValidator,繼承于驗(yàn)證策略的基類(InputValidator)
//然后重寫輸入驗(yàn)證的驗(yàn)證方法
#import "InputValidator.h"
@interface PhoneNumberValidator : InputValidator
//重載了父類的驗(yàn)證方法
- (BOOL)validateInput:(UITextField *)input;
@end
#import "PhoneNumberValidator.h"
@implementation PhoneNumberValidator
- (BOOL)validateInput:(UITextField *)input {
if (input.text.length <= 0) {
self.errorMessage = @"手機(jī)號沒有輸入";
} else {
if (input.text.length == 11 ) {
self.errorMessage = nil;
} else {
self.errorMessage = @"請輸入正確的手機(jī)號碼";
}
}
return self.errorMessage == nil ? YES : NO;
}
@end
————————————————
//在 ViewController中使用策略
- (void)viewDidLoad {
[super viewDidLoad];
self.emailField = [[CustomField alloc] initWithFrame:CGRectMake(30, 80, 300, 30)];
self.emailField.placeholder = @"請輸入郵箱";
self.emailField.delegate = self;
self.emailField.validator = [EmailValidator new];
[self.view addSubview:self.emailField];
self.phoneNumberField = [[CustomField alloc] initWithFrame:CGRectMake(30, 80 + 40, 300, 30)];
self.phoneNumberField.placeholder = @"請輸入電話號碼";
self.phoneNumberField.delegate = self;
self.phoneNumberField.validator = [PhoneNumberValidator new];
[self.view addSubview:self.phoneNumberField];
}
#pragma mark - 文本框代理
- (void)textFieldDidEndEditing:(UITextField *)textField {
CustomField *customField = (CustomField *)textField;
if ([customField validate] == NO) {
NSLog(@"====================>>>>>>>>>>>> %@",customField.validator.errorMessage);
}
}
//相當(dāng)于在此ViewController的textFieldDidEndEditing:中寫了
- (void)textFieldDidEndEditing:(UITextField *)textField {
if(textField == 郵箱textField){
if (textField.text.length <= 0) {
NSLog(@"郵箱沒有輸入");
}
else{
NSLog(@"");
}
}
else if(textField == 手機(jī)textField){
if (textField.text.length <= 0) {
NSLog(@"手機(jī)號沒有輸入");
} else {
if (textField.text.length == 11 ) {
NSLog(@"");
} else {
NSLog(@"請輸入正確的手機(jī)號碼") ;
}
}
}
}
————————————————
https://blog.csdn.net/qq_19678579/article/details/86162604
https://cloud.tencent.com/developer/article/1781975