美文网首页
iOS --设计模式(4、CommandPattern命令模式)

iOS --设计模式(4、CommandPattern命令模式)

作者: oneYing | 来源:发表于2017-12-18 22:26 被阅读150次

命令模式是将请求封装成对象。

例如下图 屏幕快照 2017-12-17 下午10.33.22.png
你要做一个控制家庭智能电器的app。每一个电器的控制都要其自己的api。

很明显,要使用的主UI是UITableView,而对于每个接口的调用,肯定不会去写一坨if else。正面登场的就是命令模式。

1 先介绍一下厂商提供的智能电器接口:

1.1 电灯

#import <Foundation/Foundation.h>
@interface Light : NSObject
@property (nonatomic, strong) NSString *name;
// 初始化电灯并设置电灯的名称
- (instancetype)initWithName:(NSString *)name;
// 打开电灯
- (void)on;
// 关闭电灯
- (void)off;
@end

1.2 音响

#import <Foundation/Foundation.h>
@interface Stereo : NSObject
@property (nonatomic, strong) NSString *stereoName;
// 初始化音响并设置音响的名称
- (instancetype)initWithName:(NSString *)name;
// 打开音响
- (void)stereoOn;
// 关闭音响
- (void)stereoOff;
@end

这两个api来自己同一个厂商,所以接口相似

2 开始命令模式

2.1 首先,设计一个Command的接口

#import <Foundation/Foundation.h>
@protocol Command <NSObject>
// 执行命令
- (void)execute;
@end

2.2 然后,设计一个BaseCommand的基类,并且遵守上述协议接口

#import <Foundation/Foundation.h>
#import "Command.h"
@interface BaseCommand : NSObject<Command>
@end

对于协议中的接口,基类并不做具体的实现。

2.3 设计一个控制开灯的命令

一个继承BaseCommand的类,其初始化方法中需要接收厂商提供的Light对象,并在execute方法的实现中调用ligth对象的on接口

#import "BaseCommand.h"
@class Light;
@interface LightOnCommand : BaseCommand
// 初始化开灯命令
- (instancetype)initWith:(Light *)light;
@end

其内部实现

#import "LightOnCommand.h"
#import "Light.h"
@interface LightOnCommand ()
@property (nonatomic, strong) Light *light;
@end
@implementation LightOnCommand
- (instancetype)initWith:(Light *)light{
    self = [super init];
    if (self) {
        self.light = light;
    }
    return self;
}
- (void)execute{
    [super execute];
    [self.light on];
}
@end

2.4 设计一个控制关灯的命令

与上述命令实现类似,只是其execute命令的实现为调用灯的off接口

2.5设计一个控制音响打/开关闭的接口

同上

3 功能实现

3.1 自定义UITableViewCell

#import "Command.h"
@interface ControlCell : UITableViewCell
// 传递开/关命令 及电器名称
- (void)setOnCommand:(id<Command>)onCommand offCommand:(id<Command>)offCommand slotName:(NSString *)name;
@end

在.m实现里,分别 用变量保存上述开/关 命令,并在触发cell中的Button点击事件时,调用相应命令的execute方法

- (void)setOnCommand:(id<Command>)onCommand offCommand:(id<Command>)offCommand slotName:(NSString *)name{
    _onCommand = onCommand;
    _offCommand = offCommand;
    _slot.text = name;
}

- (IBAction)appliancesOn:(id)sender {
    [_onCommand execute];
}

- (IBAction)appliancesOff:(id)sender {
    [_offCommand execute];
}

3.2数据源的创建

分别用三个数组来存放一一对应的电器的开命令、关命令及名称

// 开命令
@property (nonatomic, strong) NSMutableArray<id<Command>> *onCommands;
// 关命令
@property (nonatomic, strong) NSMutableArray<id<Command>> *offCommands;
// 电器名称
@property (nonatomic, strong) NSMutableArray<NSString *> *slotNames;

onCommands及slotNames数组的初始化

-(NSMutableArray *)onCommands{
    if (_onCommands == nil) {
        _onCommands = [NSMutableArray new];
        _slotNames = [NSMutableArray new];
        LightOnCommand *ligthOn = [[LightOnCommand alloc] initWith:_livingRoomLight];
        [_onCommands addObject:ligthOn];
        [_slotNames addObject:_livingRoomLight.name];
        
        ligthOn = [[LightOnCommand alloc] initWith:_kitchenLight];
        [_onCommands addObject:ligthOn];
        [_slotNames addObject:_kitchenLight.name];
        
        StereoOnWithCDCommand *stereoOn = [[StereoOnWithCDCommand alloc] initWithStereo:_livingRoomStereo];
        [_onCommands addObject:stereoOn];
        [_slotNames addObject:_livingRoomStereo.stereoName];
        NoCommand *noCommand = [NoCommand new];
        for (int i = 0; i < 5; ++i) {
            [_onCommands addObject:noCommand];
            [_slotNames addObject:@"NULL"];
        }
    }
    return _onCommands;
}

offCommands数组与上述相似

3.3 给tablewView赋值

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    ControlCell *cell = [tableView dequeueReusableCellWithIdentifier:CELLID forIndexPath:indexPath];
    NSUInteger slot = indexPath.row;
    BaseCommand *onCo = _onCommands[slot];
    BaseCommand *offCo = _offCommands[slot];
    [cell setOnCommand:onCo offCommand:offCo slotName:_slotNames[slot]];
    onCo.lastComDelegate = self;
    offCo.lastComDelegate = self;
    return cell;
}

完美实现
demo地址
码云

相关文章

网友评论

      本文标题:iOS --设计模式(4、CommandPattern命令模式)

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