• iOS面试题使用到的设计模式


    iOS中使用到了许多的设计模式,其中包括单例模式、委托模式、观察者模式、MVC模式等

    下面来分别进行讲解:

    一单例模式

    单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

    1.单例模式的要点:

      显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

    2.单例模式的优点:

      1.实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。
      2.灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
     
    IOS中的单例模式
      在objective-c中要实现一个单例类,至少需要做以下四个步骤:
      1、为单例对象实现一个静态实例,并初始化,然后设置成nil,
      2、实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,
      3、重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,
      4、适当实现allocWitheZone,copyWithZone,release和autorelease。
     1 static SurveyRunTimeData *sharedObj = nil; //第一步:静态实例,并初始化。
     2 @implementation SurveyRunTimeData
     3 + (SurveyRunTimeData*) sharedInstance  //第二步:实例构造检查静态实例是否为nil
     4 {
     5     @synchronized (self)
     6     {
     7         if (sharedObj == nil)
     8         {
     9             [[self alloc] init];
    10         }
    11     }
    12     return sharedObj;
    13 }
    14 
    15 + (id) allocWithZone:(NSZone *)zone //第三步:重写allocWithZone方法
    16 {
    17     @synchronized (self) {
    18         if (sharedObj == nil) {
    19             sharedObj = [super allocWithZone:zone];
    20             return sharedObj;
    21         }
    22     }
    23     return nil;
    24 }
    25 
    26 - (id) copyWithZone:(NSZone *)zone //第四步
    27 {
    28     return self;
    29 }
    30 
    31 - (id) retain
    32 {
    33     return self;
    34 }
    35 
    36 - (unsigned) retainCount
    37 {
    38     return UINT_MAX;
    39 }
    40 
    41 - (oneway void) release
    42 {
    43     
    44 }
    45 
    46 - (id) autorelease
    47 {
    48     return self;
    49 }
    50 
    51 - (id)init
    52 {
    53     @synchronized(self) {
    54         [super init];//往往放一些要初始化的变量.
    55         return self;
    56     }
    57 }
    58 
    59 @end
    单例model

    二 委托模式

    代理模式是用来用于改变或控制其他对象,顾名思义就是委托别人去做事情。

    委托的作用有两个,一个是传值,一个是传事件。
    1.所谓传值经常用在B类要把自己的一个数据或者对象传给A类,让A类去展示或者处理。(这个作用在两个View视图之间传递参数的时候特别有用)
    2.所谓传事件就是A类发生了什么事,把这件事告诉关注自己的人,也就是委托的对象,由委托的对象去考虑发生这个事件后应该做出什么反映。简单的说,假如A类发生某个事件,它本身并不出来,而是通过委托delegate的形式,让它的委托对象B类去处理(当然委托对象B就要实现委托中的方法)。
     

    Delegate 的定义:

    (1)Delegate 是一个对象, 其类型为 id  (anonymous type: 匿名类型);

    (2) Delegate 的引用通常是一个实例变量 (instance variable), 命名为 delegate;

    (3)Delegate 内所用的方法是 访问模式 (Accessors pattern) 

    Delegate Message 的命名:

    发给Delegate的消息 通常带有(should, will, did) 之一。     

    should:期待delegate返回一个值;

    will:表示变化发生之前 要做的事情;

    did : 表示变化发生之后 要做的事情。

    Cocoa Touh 的很多类都不同程度地用到Delgete。 比如: NSTextField, NSTableView。  其中 NSTableView 还用到了 Data Source。

    其实,Data Source 也是一种委托。 Data Source 减少了 View 与 Model 之间的耦合性。    其中 , NSAppplication 实现了几十个委托方法。

    Delegate 使用的注意事项:

    Delegate 是一个 ID 类型的对象, 同样存在创建和释放问题。 对于Data Source , 只有Data Source的使用者 (比如Table View)释放后, Data Souce 才能被释放。 否则, 就会出现crash。 因为在table view 获取数据时, 数据已经不见了。   

    Delegate 可用在多个场景下,比如对象间的数据交互,   不同视图之间的行为交互。 若仅仅是数据交互, 可实现的方法还有很多。 Delegate 尤其适用于视图之间的行为交互。

    委托模式的实现,也可以通过Block来实现,但仅适合一次性回调执行的代码。

    delegate的优势:

    1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。

    2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误

    3.协议必须在controller的作用域范围内定义

    4.在一个应用中的控制流程是可跟踪的并且是可识别的;

    5.在一个控制器中可以定义定义多个不同的协议,每个协议有不同的delegates

    6.没有第三方对象要求保持/监视通信过程。

    7.能够接收调用的协议方法的返回值。这意味着delegate能够提供反馈信息给controller

    缺点:

    1.需要定义很多代码:1.协议定义;2.controller的delegate属性;3.在delegate本身中实现delegate方法定义

    2.在释放代理对象时,需要小心的将delegate改为nil。一旦设定失败,那么调用释放对象的方法将会出现内存crash

    3.在一个controller中有多个delegate对象,并且delegate是遵守同一个协议,但还是很难告诉多个对象同一个事件,不过有可能。

    三 观察者模式

         在观察者模式中,一个对象任何状态的变更都会通知另外的对改变感兴趣的对象。这些对象之间不需要知道彼此的存在,这其实是一种松耦合的设计。当某个属性变化的时候,我们通常使用这个模式去通知其它对象。
        此模式的通用实现中,观察者注册自己感兴趣的其它对象的状态变更事件。当状态发生变化的时候,所有的观察者都会得到通知。苹果的推送通知(Push Notification)就是一个此模式的例子。
    如果你要遵从MVC模式的概念,你需要让模型对象和视图对象在不相互直接引用的情况下通信。这正是观察者模式的用武之地。
    Cocoa通过通知(Notifications)和Key-Value Observing(KVO)来实现观察者模式。
     
    通知(Notifications
       不要和远程推送以及本地通知所混淆,通知是一种基于订阅-发布模式的模型,它让发布者可以给订阅者发送消息,并且发布者不需要对订阅者有任何的了解。
        通知在苹果官方被大量的使用。举例来说,当键盘弹出或者隐藏的时候,系统会独立发送UIKeyboardWillShowNotification/UIKeyboardWillHideNotification通知。当你的应用进入后台运行的时候,系统会发送一个UIApplicationDidEnterBackgroundNotification通知。
     
    注意:打开UIApplication.h,在文件的末尾,你将看到一个由系统发出的超过20个通知组成的列表。
     
    使用通知(Notifications)
    1 [[NSNotification  CenterdefaultCenter] postNotificationName:@"自定义通知名"  
    2                                                     object:self  
    3                                                   userInfo:{自定义所带的参数NSDictionary}];
    4 
    5 [[NSNotification  CenterdefaultCenter] addObserver:self selector:@selector(响应的方法:) name:@"自定义的要接受通知名" object:nil];   
    6 
    7 [[NSNotificationCenterdefaultCenter] removeObserver:self];  
    notification model

    在IOS应用开发中有一个”Notification Center“的概念。它是一个单例对象,允许当事件发生时通知一些对象。它允许我们在低程度耦合的情况下,满足控制器与一个任意的对象进行通信的目的。 这种模式的基本特征是为了让其他的对象能够接收到在该controller中发生某种事件而产生的消息,controller用一个key(通知名称)。 这样对于controller来说是匿名的,其他的使用同样的key来注册了该通知的对象(即观察者)能够对通知的事件作出反应。

    优势:

      1.不需要编写多少代码,实现比较简单;

    2.对于一个发出的通知,多个对象能够做出反应,即1对多的方式实现简单

    3.controller能够传递context对象(dictionary),context对象携带了关于发送通知的自定义的信息

    缺点:

    1.在编译期不会检查通知是否能够被观察者正确的处理; 

    2.在释放注册的对象时,需要在通知中心取消注册;

    3.在调试的时候应用的工作以及控制过程难跟踪;

    4.需要第三方对喜爱那个来管理controller与观察者对象之间的联系;

    5.controller和观察者需要提前知道通知名称、UserInfo dictionary keys。如果这些没有在工作区间定义,那么会出现不同步的情况;

    6.通知发出后,controller不能从观察者获得任何的反馈信息。

     Key-Value Observing(KVO)模式

    在KVO中,一个对象可以要求在它自身或者其它对象的属性发送变化的时候得到通知。如果你对KVO感兴趣的话,你可以更进一步的阅读这篇文章:Apple’s KVO Programming Guide.

    KVO

    KVO是一个对象能够观察另外一个对象的属性的值,并且能够发现值的变化。前面两种模式更加适合一个controller与任何其他的对象进行通信,而 KVO更加适合任何类型的对象侦听另外一个任意对象的改变(这里也可以是controller,但一般不是controller)。这是一个对象与另外一 个对象保持同步的一种方法,即当另外一种对象的状态发生改变时,观察对象马上作出反应。它只能用来对属性作出反应,而不会用来对方法或者动作作出反应。

    优点:

    1.能够提供一种简单的方法实现两个对象间的同步。例如:model和view之间同步;

    2.能够对非我们创建的对象,即内部对象的状态改变作出响应,而且不需要改变内部对象(SKD对象)的实现;

    3.能够提供观察的属性的最新值以及先前值;

    4.用key paths来观察属性,因此也可以观察嵌套对象;

    5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察

    缺点:

    1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;

    2.对属性重构将导致我们的观察代码不再可用;

    3.复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向;

    4.当释放观察者时不需要移除观察者。

    四 MVC模式

    Model-View-Controller :模型-视图-控制器,复合模式。

    MVC是由数个设计模式结合起来的模式。

    MVC模式浅谈

    M,Model模型:

      模型持有所有的数据、状态和程序逻辑。

      模型没有注意到视图和控制器,虽然它提供了操纵和检索状态的接口,并发送状态改变通知给观察者。

    V,View 视图:

      视图用来呈现模型。

      视图通常直接从模型中取得它需要显示的状态与数据。

    C,Controller 控制器

      控制器取得用户的输入并解读其对模型的意思。

      控制器把控制逻辑从视图中分离,让模型和视图之间解耦。通过保持控制器和视图之间的松耦合,设计就更有弹性而且容易扩展。

    MVC模式通过建立一个“发布/订阅”(publish-subscribe)的机制来分离视图和模型。发布-订阅(publish-subscribe)机制的目标是发布者,它发出通知时并不需知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。MVC模式最重要的是用到了Observer(观察者模式),正是观察者模式实现了发布-订阅(publish-subscribe)机制,实现了视图和模型的分离。因此谈到MVC模式就必须谈到观察者模式。

    MVC中的设计模式

      模型利用观察者模式让控制器和视图可以随最新的状态改变而更新。

      模型对视图和控制器一无所知,它们之间是完全解耦的,模型只知道有一些观察者它需要通知。模型还提供一些接口,供视图和控制器获得并设置状态。

      视图和控制器实现了策略模式。控制器是视图的行为,如果你希望有不同的行为,可以直接换一个控制器。

      视图内部使用组合模式来管理窗口、按钮以及其他显示组件。


    GOF四人组提出MVC模式的主要关系是由Observer(观察者模式)Composite(组合模式)和Strategy(策略模式)三个设计模式给出的。

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    策略模式:定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

    命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

  • 相关阅读:
    一个弹框表单复用create,edit表单操作
    数组去重,防抖节流,渲染几万条数据不卡页面,32个手撕JS,彻底摆脱初级前端
    解决vue表单回显数据无法修改的问题
    正则
    将UTC时间转换为当地的时间
    Vue页面上实时显示当前时间,每秒更新
    互联网协议
    记录:批量重命名文件夹下的文件
    IdentityServer4 无法登录,一直跳转登录界面
    同解与等价
  • 原文地址:https://www.cnblogs.com/tony_cap/p/3774950.html
Copyright © 2020-2023  润新知