面试专题(重难点)

iOS中常用的几种设计模式

2021-03-25  本文已影响0人  清风_____
1.代理模式

代理模式完成委托方交给的任务,委托方有一些任务自己不想完成,但是还需要要实现,则将该任务存放到协议中,由代理完成.但是代理并不会主动的执行任务,需要委托方通知代理。

/*实现
说明:代理是一对一的,响应栈内最近一个代理对象(多为传值,相连的页面)
代理的使用,可以简单的概括为两个三步走,即创建代理的三步和使用代理的三步。 
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方法。

/*实现
说明:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 简而言之,就是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程序中,这一份资源是共享的。
提供一个固定的实例创建方法。

//实现
/*一个单例类,保证一个类仅有一个实例,在整个程序中只有一个实例,并且提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序(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.策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

//实现
/*策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
简而言之就是把控制其中的一大串 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

上一篇 下一篇

猜你喜欢

热点阅读