美文网首页
ios设计模式——适配器模式

ios设计模式——适配器模式

作者: 小书同学 | 来源:发表于2019-01-15 22:54 被阅读0次

    一、什么是适配器?

      举个例子,我们有些人买手机,买的是港版,会发现港版的电源插头跟我们的不一样,基本都是三角,而且它的三角还跟国内的不一样,导致我们必须用一个转换头才行。为了让港版电源插头在国内也能使用,就用转换头,这个转换头就是适配器。
      在开发过程中,我们会遇到旧代码与新接口无法兼容的问题,这时候,引入适配器,就可以实现新接口调用旧代码的功能。

    二、适配器模式(Adapter Pattern)

    适配器模式,就是使得原本由于接口不兼容而不能一起工作的类可以一起工作。简单的说,适配器模式就是是用来解决使用不兼容接口的问题的方案

    1、类适配器

    这种适配器模式,就是通过继承来适配两个接口。
    在Objective-C中,有protocol,我们可以通过实现protocol,同时又继承超类,达到多重继承的效果。

    类适配器.png

    Target : protocol协议,也就是目标接口,或称为标准接口
    Adaptee :父类,也就是被适配者。一个已经存在的,具有某种需要的特殊功能,但又不符合我们既有的标准接口的类。

      图中,Adapter实现了协议Target,同时又继承了父类Adaptee。这样就让Adapter既是一个Target类型,也是一个Adaptee类型。在Adapter中,实现了协议Target中的request()方法,没有重载Adaptee的方法,而是在request()方法中,执行[super specificRequest]。这样就达到了,通过一个目标接口的调用,去使用一个已有的某个功能。

    //Target.h
    @protocol Target <NSObject>
    - (void)request;
    @end
    
    //Adaptee.h
    @interface Adaptee : NSObject
    - (void)specificRequest;
    @end
    
    //Adapter.h
    @interface Adapter : Adaptee <Target>
    @end
    
    //Adapter.m
    @implementation Adapter
    - (void)request{
        NSLog(@"Adapter request()");
        [super specificRequest];
    }
    @end
    

      类适配器的重点是类的继承,这样我们的适配器可以根据需求去创建需要的子类类型。

    2、对象适配器

      对象适配器与上面的类适配器有所不同,对象适配器不需要继承被适配者,而是组合一个对它的引用。


    对象适配器.png

    这个图跟上面的类适配器的图相似,只是Adapter与Adaptee之间的关系不再是继承,而是包含关系。在这种关系中,Adapter中保持了一个队Adaptee的引用。这样在Adapter的request()方法中,直接使用[adaptee specificReuqest],以此间接的访问Adapteede的方法。

    //NewAdapter.h
    @interface NewAdapter : NSObject<Target>
    @end
    
    //NewAdapter.m
    @interface NewAdapter()
    @property (nonatomic, strong) Adaptee *adaptee;
    @end
    @implementation NewAdapter
    - (void)request{
        [_adaptee specificRequest];
    }
    @end
    

    3、差别

      类适配器对象适配器是实现适配器模式的两种不同方式,但是达到的目的都是一样的。那么两者有什么差别了?

    类适配器
      1、需要创建Adaptee的子类,所以只针对单一的具体的Adaptee类,把Adaptee适配到Target;
      2、由于创建了子类,可以重载Adaptee的方法;
      3、由于是Adaptee的子类,可以直接访问Adaptee。

    对象适配器
      1、可以适配多个Adaptee及其子类;
      2、难以重载Adaptee的方法,需要借助于Adaptee的子类,而不是Adaptee本身;
      3、需要额外的指针来间接访问Adaptee或其方法。

    4、何时使用适配器模式

    1、已有类的接口与需求不匹配;
    2、想要一个可复用的类,该类能够同可能带有不兼容接口的其他类协同工作。
    3、需要适配一个类的几个不同子类,可是让每一个子类去子类化一个类适配器又太麻烦,可以使用对象适配器来适配其父类的接口。

    三、委托Delegate

      我们在iOS开发过程中,最常见的就是delegate,比如需要实现UITableView的时候,我们会用到UITableViewDelegate。
      我们理理这个delegate。使用过程中,我们不需要知道UITableView中是如何调用这个delegate的,只需要在对应需要显示UITableView的地方实现UITableViewDelegate这个协议,而UITableView也不需要知道是如何实现具体的内容的。这样两者的关联通道仅仅是一个delegate而已。
      接下来,用平时的代码来自定义一个delegate。

    @protocol btnClickedDelegate <NSObject>
    //  定义了一个UITablViewCell中Button被点击的delegate
    -(void)cellBtnClicked:(NSInteger)section row:(NSInteger)row;
    @end
    

    接着在Controller中实现了对应protocol

    @interface TestViewController ()<UITableViewDelegate,UITableViewDataSource,btnClickedDelegate>{
            NSString *_cellIdentifier;
    }
    @end
    
    @implementation NoviceGuideViewController
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        TestTableViewCell *cell = (TestTableViewCell *)[tableView dequeueReusableCellWithIdentifier:_cellIdentifier];
        cell.delegate = self; //传递delegate到cell中
        return cell;
    }
    - (void)cellBtnClicked:(NSInteger)section row:(NSInteger)row{
        // 省去实现的代码
    }
    @end
    

    适配器实现了,那么就是被适配者的回调
    .h文件

    @interface TestTableViewCell : UITableViewCell
    @property (weak, nonatomic) id<btnClickedDelegate> delegate;
    @end
    

    .m文件

    - (IBAction)buttonClick:(id)sender {
        if(self.delegate && [self.delegate respondsToSelector:@selector(cellBtnClicked:row:)]){
            [self.delegate cellBtnClicked:section row:row];
        }
    }
    

      这样,整个逻辑就完成了。
      梳理一下执行流程:当cell中的按钮被点击的时候,会通过cell中的delegate,去调用cell中的引用,也就是Controller,然后controller中对对应的协议的实现,就是其后续的自己的逻辑流程了。

    四、用Objective-C的块

      只需将上面的delegate换成block就可以了。
    只是有几个地方需要注意:
    1、就是controller不在需要实现delegate了;
    2、controller中直接声明block,传递给cell;
    3、cell中仍然持有对block的引用;
    4、cell中直接对block进行调用。

    相关文章

      网友评论

          本文标题:ios设计模式——适配器模式

          本文链接:https://www.haomeiwen.com/subject/abvudqtx.html