1.代理模式
代理模式完成委托方交给的任务,委托方有一些任务自己不想完成,但是还需要要实现,则将该任务存放到协议中,由代理完成.但是代理并不会主动的执行任务,需要委托方通知代理。
-
1.1应用场景
当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。 -
1.2优势
解耦合 -
1.3敏捷原则
开放-封闭原则 -
1.4实例
tableview的 数据源delegate,通过和protocol的配合,完成委托诉求。列表row个数delegate,自定义的delegate。
/*实现
说明:代理是一对一的,响应栈内最近一个代理对象(多为传值,相连的页面)
代理的使用,可以简单的概括为两个三步走,即创建代理的三步和使用代理的三步。
1.创建代理:
2.创建代理协议
3.声明代理方法
4.声明代理属性
5.使用代理:
6.遵守代理协议
7.设置代理对象
8.实现代理方法
代码实现:下面我们直接上代码,实现点击代理按钮,上面的label显示“代理传的值”*/
//创建代理(传值的页面)
//.h文件中
#import <UIKit/UIKit.h>
//创建代理协议
@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" //创建了代理的页面
@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. 观察者模式(通知机制,KVO机制)
观察者模式本质上是一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。
- 2.1应用场景
一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息。 - 2.2优势
解耦合 - 2.3敏捷原则
接口隔离原则,开放-封闭原则 - 2.4实例
Notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。
/*实现
说明:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 简而言之,就是A和B,A对B的变化感兴趣,就注册A为观察者,当B发生变化时通知A,告知B发生了变化。这个也叫做经典观察者模式。*/
————————————————
//1.通知机制
//注册通知接收者的代码(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所发的Notification…传值请用userInfo,而不是object
问题2. iOS中,广播通知(broadcast notification)/本地通知(local notification)/推送通知(push notification)有什么区别和不同?
出了名字相似以外,广播通知和其他两个通知是完全不一样的: 广播通知是cocoatouch中观察者模式的一种机制, 实现应用内部多个对象的通信…本地通知和推送通知中的"通知"是一种"提示"…通过警告框,发出声音,振动和在应用图标上显示数组等,在计划时间到达时,本地通知通过本地iOS发出,推送通知由第三方程序发送给苹果远程服务器,再由远程服务器推送给iOS特定应用.
————————————————
*/
3.单例模式
单例模式可以保证App在程序运行中,一个类只有唯一个实例,从而做到节约内存。
在整个App程序中,这一份资源是共享的。
提供一个固定的实例创建方法。
- 3.1应用场景
确保程序运行期某个类,只有一份实例,用于进行资源共享控制。 - 3.2优势
使用简单,延时求值,易于跨模块 - 3.3敏捷原则
单一职责原则 - 3.4实例
[UIApplication sharedApplication]。 - 3.5注意事项
确保使用者只能通过 getInstance方法才能获得,单例类的唯一实例。
java,C++中使其没有公有构造函数,私有化并覆盖其构造函数。
object c中,重写allocWithZone方法,保证即使用户用 alloc方法直接创建单例类的实例,返回的也只是此单例类的唯一静态变量。
//实现
/*一个单例类,保证一个类仅有一个实例,在整个程序中只有一个实例,并且提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序(APP)退出时由系统自动释放这部分内存。
在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次),一般用于工具类。例如:登陆控制器,网络数据请求,音乐播放器等一个工程需要使用多次的控制器或方法。
如工具类、公共跳转类等经常调用的类,都会采用单例模式。*/
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.策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
- 4.1应用场景
定义算法族,封装起来,使他们之间可以相互替换。 - 4.2优势
使算法的变化独立于使用算法的用户 - 4.3敏捷原则
接口隔离原则;
多用组合,少用继承;
针对接口编程,而非实现。 - 4.4实例
排序算法,NSArray的sortedArrayUsingSelector;经典的鸭子会叫,会飞案例。 - 4.5注意事项
1、剥离类中易于变化的行为,通过组合的方式嵌入抽象基类
2、变化的行为抽象基类为,所有可变变化的父类
3、用户类的最终实例,通过注入行为实例的方式,设定易变行为
防止了继承行为方式,导致无关行为污染子类。完成了策略封装和可替换性。
//实现
/*策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
简而言之就是把控制其中的一大串 if...else... 或者 switch()单独抽出来写成一些列的算法文件, 减轻了ViewController的负担同时也简化操作,提高代码维护性。算法可以自由切换,避免使用多重条件判断,扩展性良好。
如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。*/
————————————————
//在UITextField的子类CustomField中
#import <UIKit/UIKit.h>
#import "InputValidator.h"
@interface CustomField : UITextField
//抽象的策略
@property (nonatomic, strong) InputValidator *validator;
/**
初始化textField
@param frame frame
@return 实例对象
*/
- (instancetype)initWithFrame:(CGRect)frame;
/**
验证输入合法性
@return 是否合法,不合法,读取InputValidator当中的errorMessage
*/
- (BOOL)validate;
@end
//.m
- (BOOL)validate {
return [self.validator validateInput:self];
}
————————————————
//创建一个验证策略的基类 InputValidator
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface InputValidator : NSObject
/**
策略的输入
@param input input
@return 如果为YES,表示测试通过,如果为NO,表示测试不通过
*/
- (BOOL)validateInput:(UITextField *)input;
//当validateInput为NO的时候,我们来读取errorMessage
@property (nonatomic, strong) NSString *errorMessage;
@end
#import "InputValidator.h"
@implementation InputValidator
- (BOOL)validateInput:(UITextField *)input {
return NO;
}
@end
————————————————
//创建 一个邮箱验证方法类EmailValidator,继承于验证策略的基类(InputValidator)
//然后重写输入验证的验证方法
#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
————————————————
//创建 一个手机验证方法类PhoneNumberValidator,继承于验证策略的基类(InputValidator)
//然后重写输入验证的验证方法
#import "InputValidator.h"
@interface PhoneNumberValidator : InputValidator
//重载了父类的验证方法
- (BOOL)validateInput:(UITextField *)input;
@end
#import "PhoneNumberValidator.h"
@implementation PhoneNumberValidator
- (BOOL)validateInput:(UITextField *)input {
if (input.text.length <= 0) {
self.errorMessage = @"手机号没有输入";
} else {
if (input.text.length == 11 ) {
self.errorMessage = nil;
} else {
self.errorMessage = @"请输入正确的手机号码";
}
}
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);
}
}
//相当于在此ViewController的textFieldDidEndEditing:中写了
- (void)textFieldDidEndEditing:(UITextField *)textField {
if(textField == 邮箱textField){
if (textField.text.length <= 0) {
NSLog(@"邮箱没有输入");
}
else{
NSLog(@"");
}
}
else if(textField == 手机textField){
if (textField.text.length <= 0) {
NSLog(@"手机号没有输入");
} else {
if (textField.text.length == 11 ) {
NSLog(@"");
} else {
NSLog(@"请输入正确的手机号码") ;
}
}
}
}
————————————————
https://blog.csdn.net/qq_19678579/article/details/86162604
https://cloud.tencent.com/developer/article/1781975
网友评论