美文网首页
iOS设计模式之适配器模式上

iOS设计模式之适配器模式上

作者: 点滴86 | 来源:发表于2024-05-22 00:03 被阅读0次

    适配器模式

    适配器模式的原理与实现

    适配器模式的英文是"Adapter Design Pattern"。这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。
    适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。具体的代码示例如下。其中DMTarget表示要转化成的接口定义。DMAdaptee是一组不兼容DMTarget接口定义的接口,DMAdaptor 将DMAdaptee转化成一组符合DMTarget接口定义的接口。

    @protocol DMTarget <NSObject>
    
    - (void)f1;
    
    - (void)f2;
    
    - (void)fc;
    
    @end
    
    @interface DMAdaptee : NSObject
    
    - (void)fa;
    
    - (void)fb;
    
    - (void)fc;
    
    @end
    
    @implementation DMAdaptee
    
    - (void)fa
    {
        
    }
    
    - (void)fb
    {
        
    }
    
    - (void)fc
    {
        
    }
    
    @end
    
    // 基于继承模式实现 适配器模式
    @interface DMAdaptor : DMAdaptee <DMTarget>
    
    @end
    
    @implementation DMAdaptor
    
    - (void)f1
    {
        [self fa];
    }
    
    - (void)f2
    {
        // 自己实现
    }
    
    // 这里fc 函数不用实现,直接继承自Adaptee,这是跟对象适配器最大的不同点
    
    @end
    
    @protocol DMTarget <NSObject>
    
    - (void)f1;
    
    - (void)f2;
    
    - (void)fc;
    
    @end
    
    @interface DMAdaptee : NSObject
    
    - (void)fa;
    
    - (void)fb;
    
    - (void)fc;
    
    @end
    
    @implementation DMAdaptee
    
    - (void)fa
    {
        
    }
    
    - (void)fb
    {
        
    }
    
    - (void)fc
    {
        
    }
    
    @end
    
    // 对象适配器
    @interface DMAdaptor : NSObject <DMTarget>
    
    - (instancetype)initWithAdaptee:(DMAdaptee *)adaptee;
    
    @end
    
    @interface DMAdaptor ()
    
    @property (nonatomic, strong) DMAdaptee *adaptee;
    
    @end
    
    @implementation DMAdaptor
    
    - (instancetype)initWithAdaptee:(DMAdaptee *)adaptee
    {
        if (self = [super init]) {
            self.adaptee = adaptee;
        }
        
        return self;
    }
    
    - (void)f1
    {
        [self.adaptee fa];
    }
    
    - (void)f2
    {
        // 自己实现
    }
    
    - (void)fc
    {
        [self.adaptee fc];
    }
    
    @end
    

    针对这两种实现方式,在实际的开发中,到底该如何选择使用那一种呢?判断的标准主要有两个,一个是DMAdaptee接口的个数,另一个是DMAdaptee 和DMTarget的契合程度。

    • 如果DMAdaptee接口并不多,那两种实现方式都可以。
    • 如果DMAdaptee接口很多,而且DMAdaptee和DMTarget 接口定义大部分都相同,那推荐使用类适配器,因为DMAdaptor复用父类DMAdaptee的接口,比起对象适配器的实现方式,DMAdaptor的代码量要少一些。
    • 如果DMAdaptee接口很多,而且DMAdaptee和DMTarget 接口定义大部分都不相同,那推荐使用对象适配器,因为组合结构相对于继承更加灵活。

    适配器模式应用场景总结

    1. 封装有缺陷的接口设计
      假设依赖的外部系统在接口设计方面有缺陷(比如包含大量静态方法),引入之后会影响到自身代码的可测试性。为了隔离设计上的缺陷,希望对外部系统提供的接口进行二次封装,抽象出更好的接口设计,这个时候就可以使用适配器模式了。
    // 这个类来自外部系统,无权对其进行修改
    @interface DMCD : NSObject
    
    + (void)staticFunction1;
    
    - (void)uglyNamingFunction2;
    
    - (void)tooManyParamsFunction3ParamOne:(NSString *)paramOne paramTwo:(NSString *)paramTwo paramThree:(NSString *)paramThree;
    
    - (void)lowPerformanceFunction4;
    
    @end
    
    @implementation DMCD
    
    + (void)staticFunction1
    {
        
    }
    
    - (void)uglyNamingFunction2
    {
        
    }
    
    - (void)tooManyParamsFunction3ParamOne:(NSString *)paramOne paramTwo:(NSString *)paramTwo paramThree:(NSString *)paramThree
    {
        
    }
    
    - (void)lowPerformanceFunction4
    {
        
    }
    
    @end
    
    // 使用适配器模式进行重构
    @interface DMParamsWrapper :NSObject
    
    @property (nonatomic, strong) NSString *paramOne;
    
    @property (nonatomic, strong) NSString *paramTwo;
    
    @property (nonatomic, strong) NSString *paramThree;
    
    @end
    
    // 使用适配器模式进行重构
    @protocol DMCDTarget <NSObject>
    
    - (void)function1;
    
    - (void)function2;
    
    - (void)function3:(DMParamsWrapper *)paramsWrapper;
    
    - (void)function4;
    
    @end
    
    // 使用适配器模式进行重构
    @interface DMCDAdaptor : NSObject <DMCDTarget>
    
    - (instancetype)initWithCD:(DMCD *)oneCD;
    
    @end
    @interface DMCDAdaptor ()
    
    @property (nonatomic, strong) DMCD *oneCD;
    
    @end
    
    @implementation DMCDAdaptor
    
    - (instancetype)initWithCD:(DMCD *)oneCD
    {
        if (self = [super init]) {
            self.oneCD = oneCD;
        }
        
        return self;
    }
    
    #pragma mark - DMCDTarget 方法
    - (void)function1
    {
        [DMCD staticFunction1];
    }
    
    - (void)function2
    {
        [self.oneCD uglyNamingFunction2];
    }
    
    - (void)function3:(DMParamsWrapper *)paramsWrapper
    {
        [self.oneCD tooManyParamsFunction3ParamOne:paramsWrapper.paramOne paramTwo:paramsWrapper.paramTwo paramThree:paramsWrapper.paramThree];
    }
    
    - (void)function4
    {
        [self.oneCD lowPerformanceFunction4];
    }
    
    @end
    

    2.统一多个类的接口设计
    某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为统一的接口定义,然后就可以使用多态的特性来复用代码逻辑。
    假设系统要对用户输入的文本内容做敏感词过滤,为了提高过滤的召回率,引入了多款第三方敏感词过滤系统,依次对用户输入的内容进行过滤,过滤掉尽可能多的敏感词。但是,每个系统提供的过滤接口都是不同的。这就意味着没法复用一套逻辑来调用各个系统。这个时候,就可以使用适配器模式,将所有系统的接口适配为统一的接口定义,这样就可以复用调用敏感词过滤的代码了。

    // A敏感词过滤系统提供的方法
    @interface DMASensitiveWordsFilter : NSObject
    
    // text是原始文本,方法返回用***替换敏感词之后的文本
    - (NSString *)filterSexyWords:(NSString *)text;
    
    - (NSString *)filterPoliticalWords:(NSString *)text;
    
    @end
    
    @implementation DMASensitiveWordsFilter
    
    - (NSString *)filterSexyWords:(NSString *)text
    {
        // 省略实现
        return @"";
    }
    
    - (NSString *)filterPoliticalWords:(NSString *)text
    {
        // 省略实现
        return @"";
    }
    
    @end
    
    @interface DMBSensitiveWordsFilter : NSObject
    
    - (NSString *)filter:(NSString *)text;
    
    @end
    
    @implementation DMBSensitiveWordsFilter
    
    - (NSString *)filter:(NSString *)text
    {
        // 省略实现
        return @"";
    }
    
    @end
    
    @interface DMCSensitiveWordsFilter : NSObject
    
    - (NSString *)filter:(NSString *)text mask:(NSString *)maskStr;
    
    @end
    
    @implementation DMCSensitiveWordsFilter
    
    - (NSString *)filter:(NSString *)text mask:(NSString *)maskStr
    {
        // 省略实现
        return @"";
    }
    
    @end
    
    // 未使用适配器模式之前的代码: 代码的可测试性、扩展性不好
    @interface DMRiskManagement : NSObject
    
    - (NSString *)filterSensitiveWords:(NSString *)text;
    
    @end
    
    @interface DMRiskManagement ()
    
    @property (nonatomic, strong) DMASensitiveWordsFilter *aFilter;
    
    @property (nonatomic, strong) DMBSensitiveWordsFilter *bFilter;
    
    @property (nonatomic, strong) DMCSensitiveWordsFilter *cFilter;
    
    @end
    
    @implementation DMRiskManagement
    
    - (instancetype)init
    {
        if (self = [super init]) {
            self.aFilter = [[DMASensitiveWordsFilter alloc] init];
            self.bFilter = [[DMBSensitiveWordsFilter alloc] init];
            self.cFilter = [[DMCSensitiveWordsFilter alloc] init];
        }
        
        return self;
    }
    
    - (NSString *)filterSensitiveWords:(NSString *)text
    {
        NSString *maskedText = [self.aFilter filterSexyWords:text];
        maskedText = [self.aFilter filterPoliticalWords:maskedText];
        maskedText = [self.bFilter filter:maskedText];
        maskedText = [self.cFilter filter:maskedText mask:@"***"];
        return maskedText;
    }
    
    @end
    
    // 使用适配器模式进行改造
    @protocol DMSensitiveWordFilter <NSObject>
    
    - (NSString *)filter:(NSString *)text;
    
    @end
    
    // 使用适配器模式进行改造
    @interface DMASensitiveWordsFilterAdaptor : NSObject <DMSensitiveWordFilter>
    
    - (instancetype)initWithASensitiveWordsFilter:(DMASensitiveWordsFilter *)wordsFilter;
    
    @end
    
    @interface DMASensitiveWordsFilterAdaptor ()
    
    @property (nonatomic, strong) DMASensitiveWordsFilter *aFilter;
    
    @end
    
    @implementation DMASensitiveWordsFilterAdaptor
    
    - (instancetype)initWithASensitiveWordsFilter:(DMASensitiveWordsFilter *)wordsFilter
    {
        if (self = [super init]) {
            self.aFilter = wordsFilter;
        }
        
        return self;
    }
    
    #pragma - DMSensitiveWordFilter 方法
    - (NSString *)filter:(NSString *)text
    {
        NSString *maskedText = [self.aFilter filterSexyWords:text];
        maskedText = [self.aFilter filterPoliticalWords:text];
        return maskedText;
    }
    
    @end
    
    // 使用适配器模式进行改造
    @interface DMBSensitiveWordsFilterAdaptor : NSObject <DMSensitiveWordFilter>
    
    - (instancetype)initWithBSensitiveWordsFilter:(DMBSensitiveWordsFilter *)wordsFilter;
    
    @end
    
    @interface DMBSensitiveWordsFilterAdaptor ()
    
    @property (nonatomic, strong) DMBSensitiveWordsFilter *bFilter;
    
    @end
    
    @implementation DMBSensitiveWordsFilterAdaptor
    
    - (instancetype)initWithBSensitiveWordsFilter:(DMBSensitiveWordsFilter *)wordsFilter
    {
        if (self = [super init]) {
            self.bFilter = wordsFilter;
        }
        
        return self;
    }
    
    #pragma - DMSensitiveWordFilter 方法
    - (NSString *)filter:(NSString *)text
    {
        NSString *maskedText = [self.bFilter filter:text];
        return maskedText;
    }
    
    
    @end
    
    // 使用适配器模式进行改造
    @interface DMCSensitiveWordsFilterAdaptor : NSObject <DMSensitiveWordFilter>
    
    - (instancetype)initWithCSensitiveWordsFilter:(DMCSensitiveWordsFilter *)wordsFilter;
    
    @end
    
    @interface DMCSensitiveWordsFilterAdaptor ()
    
    @property (nonatomic, strong) DMCSensitiveWordsFilter *cFilter;
    
    @end
    
    @implementation DMCSensitiveWordsFilterAdaptor
    
    - (instancetype)initWithCSensitiveWordsFilter:(DMCSensitiveWordsFilter *)wordsFilter
    {
        if (self = [super init]) {
            self.cFilter = wordsFilter;
        }
        
        return self;
    }
    
    #pragma - DMSensitiveWordFilter 方法
    - (NSString *)filter:(NSString *)text
    {
        NSString *maskedText = [self.cFilter filter:text mask:@"***"];
        return maskedText;
    }
    
    
    @end
    
    // 扩展性更好,更加符合开闭原则,如果添加一个新的敏感词过滤系统,
    // 这个类完全不需要改动;而且基于接口而非实现编程,代码的可测试性更好。
    @interface DMRiskManagement : NSObject
    
    - (void)addSensitiveWordFilter:(id<DMSensitiveWordFilter>)sensitiveWordFilter;
    
    - (NSString *)filter:(NSString *)text;
    
    @end
    
    @interface DMRiskManagement ()
    
    @property (nonatomic, strong) NSMutableArray<id<DMSensitiveWordFilter>> *filters;
    
    @end
    
    @implementation DMRiskManagement
    
    - (void)addSensitiveWordFilter:(id<DMSensitiveWordFilter>)sensitiveWordFilter
    {
        [self.filters addObject:sensitiveWordFilter];
    }
    
    - (NSString *)filter:(NSString *)text
    {
        NSString *maskedText = text;
        for (id<DMSensitiveWordFilter> sensitiveWordFilter in self.filters) {
            maskedText = [sensitiveWordFilter filter:maskedText];
        }
        
        return maskedText;
    }
    
    - (NSMutableArray<id<DMSensitiveWordFilter>> *)filters
    {
        if (_filters == nil) {
            _filters = [[NSMutableArray<id<DMSensitiveWordFilter>> alloc] init];
        }
        
        return _filters;
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:iOS设计模式之适配器模式上

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