Swift教程

iOS设计模式之适配器

本文主要是介绍iOS设计模式之适配器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

定义

适配器模式:将一个类的接口转化成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

常见搭配模式

  • 命令模式
  • 代理模式
  • 单例模式

使用场景

在一下情形,自然会想到使用这一模式:

  • 已有类的接口与需求不匹配。
  • 想要一个可复用的类,该类能够同可能带有不兼容接口的其他类协作。
  • 需要适配一个类的几个不同子类,可是让每一个子类区子类化一个类适配器又不现实。

类适配器与对象适配器

有两种实现适配器的方式,一种是通过类继承来适配两个接口,这种称为类适配器,另一种方式是组合了一个对象的引用,称为对象适配器。

类适配器与对象适配器是实现适配器模式的不同方式,但是达成的目的相同。其特征对比如下表所示:

类适配器 对象适配器
只针对单一的具体Adaptee类 可以适配多个Adaptee及其子类
易于重载Adaptee的行为 难以重载Adaptee的行为,需要借助其子类对象
只有一个Adapter对象 需要额外的指针间接访问Adaptee并适配其行为

显然,委托(Delegate)模式属于对象适配器。

类图结构

首先,确立三个角色,Target(目标接口协议),Adapter(适配器),Adaptee(被适配者),其关系图如下:

类适配器

Adapter继承自Adaptee,同时也遵循Target协议,实现目标接口request接口,request的实现中调用父类的specificRequest。客户端使用Adapter调用request接口即可。

对象适配器

Adapter遵循Target协议,持有Adaptee的对象,客户端在调用Adapter的request接口时,Adapter触发[adaptee specificRequest]。

代码实现

现在有如下需求:

绘图的应用中,设置界面的颜色调整要自动设置到主界面为主界面的背景色,设置界面依赖三个滑动条分别控制颜色的RBG值。并且同时设置当前设置界面的背景色也同步修改,使得用户可以预览背景色

一、主界面获取

首先,画图的主界面肯定是全应用中唯一的,所以使用单例持有该界面,易于与其他界面进行交互。

@interface XQCoordinatingController : NSObject

@property (nonatomic, strong)ViewController *mainViewController;

+ (XQCoordinatingController *) sharedInstance;

@end

@implementation XQCoordinatingController

+ (XQCoordinatingController *) sharedInstance
{
    static XQCoordinatingController *controller;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        controller = [XQCoordinatingController new];
    });
    return controller;
}
@end

@implementation XQCanvasViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [XQCoordinatingController sharedInstance].mainViewController = self;
}

@end
复制代码

XQCoordinatingController为单例,持有主界面XQCanvasViewController,在主界面初始化时赋值。

二、颜色设置

考虑到后续可能会有增加不同设置入口,使用命令模式(后续会有命令模式的讲解)将设置主界面背景颜色设计为可重用的。

@interface XQCommand : NSObject

- (void)excute;

@end

@implementation XQCommand

@end

typedef void(^XQColorProvider)(UIColor **color);
typedef void (^XQPostColorUpdateProvider)(UIColor *color);

@interface XQSetStrokeColorCommand : XQCommand

@property (nonatomic, copy)XQColorProvider colorProvider;
@property (nonatomic, copy)XQPostColorUpdateProvider postColorProvider;

- (void)excute;

@end

@implementation XQSetStrokeColorCommand

- (void)excute{
    UIColor *color = nil;
    self.colorProvider(&color);
    [[XQCoordinatingController sharedInstance].mainViewController.view setBackgroundColor:color];
    self.postColorProvider(color);
}

@end
复制代码

1) XQCommand是命令父类,只定义了可执行的方法excute。

2) XQSetStrokeColorCommand的XQColorProvider colorProvider属性利用block抓取设置界面的颜色对象,

3) 同时又使用XQPostColorUpdateProvider postColorProvider属性将颜色值发送给设置界面更新,可能有人觉得这一步多此一举,直接在设置界面获取颜色变化设置自己的背景色不是更方便么。此用法处于两种考虑,一方面,背景颜色的设置很可能会涉及一些算法转换,这些统一放在XQSetStrokeColorCommand中比较合适,另一方面,背景颜色的设置后续可能会推给其他对象使用,这样会明确将要推送的对象。

4) 在XQSetStrokeColorCommand的excute方法中,先使用self.colorProvider(&color);获取设置界面的颜色值,然后设置到单例的主界面中,最后将颜色推给设置界面。

三、颜色变化触发

最后,在设置界面触发背景颜色命令的执行

@interface XQPaletteViewController ()

@property (nonatomic, strong)UISlider *redSlider;
@property (nonatomic, strong)UISlider *greenSlider;
@property (nonatomic, strong)UISlider *blueSlider;

@property (nonatomic, strong)XQSetStrokeColorCommand *command;

@end

@implementation XQPaletteViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.redSlider = [XQPaletteViewController slider];
    self.redSlider.frame = CGRectMake(100, 100, 100, 50);
    [self.view addSubview:self.redSlider];
    self.greenSlider = [XQPaletteViewController slider];
    self.greenSlider.frame = CGRectMake(100, 200, 100, 50);
    [self.view addSubview:self.greenSlider];
    self.blueSlider = [XQPaletteViewController slider];
    self.blueSlider.frame = CGRectMake(100, 300, 100, 50);
    [self.view addSubview:self.blueSlider];
    
    self.command = [XQSetStrokeColorCommand new];
    __weak typeof(self) weakSelf = self;
    self.command.colorProvider = ^(UIColor *__autoreleasing *color) {
        *color = [UIColor colorWithRed:weakSelf.redSlider.value
                                 green:weakSelf.greenSlider.value
                                  blue:weakSelf.blueSlider.value
                                 alpha:1.0];
        
    };
    
    self.command.postColorProvider = ^(UIColor *color) {
        weakSelf.view.backgroundColor = color;
    };
    
    [self.redSlider addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:nil];
    [self.greenSlider addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:nil];
    [self.blueSlider addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    [self.command excute];
}

+ (UISlider *)slider{
    UISlider *slider = [[UISlider alloc] init];
    slider.minimumValue = 0;
    slider.maximumValue = 1;
    return slider;
}

@end
复制代码

添加red,blue,green三个滑动条的子视图,创建XQSetStrokeColorCommand,设置获取当前界面UIColor的回调,以及推送至当前界面的颜色设置。使用KVO实时监听三个滑动条的值变化,监听到变化时,调用[self.command excute];设置主界面的背景色。

总结

适配器搭配强大的block特性,命令模式,使得功能性更加强大,降低耦合度,也利于未来扩展的可能。

这篇关于iOS设计模式之适配器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!