iOS中常用的几种设计模式

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容

  • 下面是iOS开发中比较常用的几种设计模式.详情如下所示: (一)代理模式 应用场景:当一个类的某些功能需要由别的类...
    iplaycodex阅读 1,715评论 0 1
  • (一)代理模式 应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。 优势:解耦合 敏...
    Shelley_xie阅读 395评论 0 1
  • (一)代理模式应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。优势:解耦合敏捷原则...
    蜡笔小强阅读 393评论 0 0
  • 1. 代理模式 应用场景:当一个类的某些功能需要别的类去实现,但是又不确定哪个类来实现的时候。 优势:解耦性 敏捷...
    iChuck阅读 354评论 0 0
  • 一、代理模式应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会 是哪个类实现。优势:解耦合敏捷...
    Skipper_1_422阅读 711评论 0 0