iOS设计模式:命令

2017-03-02  本文已影响49人  younger_times

视频教程-极客学院

ps:感觉打的一手好广告啊,因为自己不太爱看视频,但这类又必须看才能明白。粘贴源代码是为了以后查阅方便,也注释了自己的理解。

电视的,遥控器,电视机,接收器。遥控器发送指令,由接收器接收并转化为电视机的信号。接收器和遥控器并不是必须的。

自我理解:命令模式由Command进行了一些约束(约束规定了一些操作),具体的ConcreteCommand进行实际操作,比如发送“提高透明度”,传给了Receiver,Receiver同时对透明度的增加也是在Receiver里面完成的。Invoker则是对执行命令进行存储。Client则只是要改变的视图层给了Receiver,具体操作都在Receiver里。没事就看看,慢慢消化。

Receiver.h(Receiver)

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface Receiver : NSObject {

    CGFloat _hud;
    CGFloat _saturation;
    CGFloat _brightness;
    CGFloat _alpha;
}

/**
 *  被服务对象
 */
@property (nonatomic, weak) UIView  *clientView;#比如说,电视。

/**
 *  变暗
 *
 *  @param pamameter 操作系数
 */
- (void)makeDarker:(CGFloat)pamameter;

/**
 *  变亮
 *
 *  @param pamameter 操作系数
 */
- (void)makeLighter:(CGFloat)pamameter;

@end

#import "Receiver.h"

@implementation Receiver

- (void)setClientView:(UIView *)clientView {

    _clientView    = clientView;
    UIColor *color = _clientView.backgroundColor;
    
    [color getHue:&_hud
       saturation:&_saturation
       brightness:&_brightness
            alpha:&_alpha];
}

- (void)makeDarker:(CGFloat)pamameter {

    _brightness -= pamameter;
    _brightness  = MAX(0, _brightness);
    
    _clientView.backgroundColor = [UIColor colorWithHue:_hud
                                             saturation:_saturation
                                             brightness:_brightness
                                                  alpha:_alpha];
}

- (void)makeLighter:(CGFloat)pamameter {

    _brightness += pamameter;
    _brightness  = MIN(1, _brightness);
    
    _clientView.backgroundColor = [UIColor colorWithHue:_hud
                                             saturation:_saturation
                                             brightness:_brightness
                                                  alpha:_alpha];
}

CommandProtocol(Command)

制定协议,由UML图看出。

#import <Foundation/Foundation.h>
#import "Receiver.h"

@protocol CommandProtocol <NSObject>

@required

/**
 *  命令的执行
 */
- (void)excute;

/**
 *  撤销命令
 */
- (void)rollBackExcute;

@end

DarkerCommand(ConcreteCommand)

#import <Foundation/Foundation.h>
#import "CommandProtocol.h"

@interface DarkerCommand : NSObject <CommandProtocol>

/**
 *  与接收器绑定并设置参数
 *
 *  @param receiver 接收器
 *  @param paramter 参数
 */
- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter;

@end
#import "DarkerCommand.h"

@interface DarkerCommand ()

@property (nonatomic, weak) Receiver *receiver;
@property (nonatomic)       CGFloat   paramter;

@end

@implementation DarkerCommand

- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter {

    self = [super init];
    if (self) {
        
        self.receiver = receiver;
        self.paramter = paramter;
    }
    
    return self;
}

- (void)excute {

    [self.receiver makeDarker:self.paramter];
}

- (void)rollBackExcute {

    [self.receiver makeLighter:self.paramter];
}

LighterCommond(ConcreteCommand)

#import <Foundation/Foundation.h>
#import "CommandProtocol.h"

@interface LighterCommond : NSObject <CommandProtocol>

/**
 *  与接收器绑定并设置参数
 *
 *  @param receiver 接收器
 *  @param paramter 参数
 */
- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter;

@end
#import "LighterCommond.h"

@interface LighterCommond ()

@property (nonatomic, weak) Receiver *receiver;
@property (nonatomic)       CGFloat   paramter;

@end

@implementation LighterCommond

- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter {
    
    self = [super init];
    if (self) {
        
        self.receiver = receiver;
        self.paramter = paramter;
    }
    
    return self;
}

- (void)excute {
    
    [self.receiver makeLighter:self.paramter];
}

- (void)rollBackExcute {
    
    [self.receiver makeDarker:self.paramter];
}

@end

Invoker(Invoker)

对执行命令的存储

@interface Invoker : NSObject

+ (instancetype)shareInstance;

/**
 *  回退操作
 */
- (void)rollBack;

/**
 *  添加指令操作
 *
 *  @param command 指令
 */
- (void)addAndExcute:(id <CommandProtocol>)command;

@end
#import "Invoker.h"

@interface Invoker ()

@property (nonatomic, strong) NSMutableArray  *queue;

@end

@implementation Invoker

+ (instancetype)shareInstance {

    static Invoker *shareInstanceValue = nil;
    static dispatch_once_t oncePredicate;
    
    dispatch_once(&oncePredicate, ^{
        
        shareInstanceValue       = [[Invoker alloc] init];
        shareInstanceValue.queue = [NSMutableArray array];
    });
    
    return shareInstanceValue;
}

- (void)rollBack {

    id <CommandProtocol> command = self.queue.lastObject;
    [command rollBackExcute];
    
    [self.queue removeLastObject];
}

- (void)addAndExcute:(id <CommandProtocol>)command {

    NSParameterAssert(command);
    
    [self.queue addObject:command];
    [command excute];
}

@end

使用

#import "ViewController.h"
#import "Receiver.h"
#import "Invoker.h"
#import "DarkerCommand.h"
#import "LighterCommond.h"

typedef enum : NSUInteger {
    
    kAddButtonTag = 10, // 增加按钮枚举值
    kDelButtonTag,      // 减少按钮枚举值
    kRolButtonTag,      // 回退按钮枚举值
    
} ViewControllerEnumValue;

@interface ViewController ()

@property (nonatomic, strong) UIButton *addButton;
@property (nonatomic, strong) UIButton *delButton;
@property (nonatomic, strong) UIButton *rolButton;

@property (nonatomic, strong) Receiver *receiver;

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // 接收器
    self.receiver            = [[Receiver alloc] init];
    self.receiver.clientView = self.view;
    
    // 初始化按钮
    [self initButtons];
}

- (void)buttonsEvent:(UIButton *)button {
    
    if (button.tag == kAddButtonTag) {
        

//LighterCommond, DarkerCommand我写进了懒加载里面
        NSLog(@"增加操作");
        LighterCommond *commond = [[LighterCommond alloc] initWithReceiver:self.receiver paramter:0.1];
        [[Invoker shareInstance] addAndExcute:commond];

//Invoker 对操作进行了存储,也可以不存储,因为LighterCommond 遵守了协议。有excute方法,调用receiver执行操作。虽然我不知道这么做,是否违背命令模式。如果违背了麻烦告诉我一声。
        
    } else if (button.tag == kDelButtonTag) {

        NSLog(@"减少操作");
        DarkerCommand *commond = [[DarkerCommand alloc] initWithReceiver:self.receiver paramter:0.1];
        [[Invoker shareInstance] addAndExcute:commond];
        
    } else if (button.tag == kRolButtonTag) {
    
        NSLog(@"回退操作");
        [[Invoker shareInstance] rollBack];
    }
}

#pragma mark - 无关初始化
- (void)initButtons {
    
    // delButton
    self.delButton     = [[UIButton alloc] initWithFrame:CGRectMake(10, 25, 30, 30)];
    
    self.delButton.tag               = kDelButtonTag;
    self.delButton.layer.borderWidth = 1.f;
    
    [self.delButton setTitle:@"-"
                    forState:UIControlStateNormal];
    
    [self.delButton setTitleColor:[UIColor redColor]
                         forState:UIControlStateNormal];
    
    [self.delButton addTarget:self
                       action:@selector(buttonsEvent:)
             forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.delButton];
    
    // addButton
    self.addButton     = [[UIButton alloc] initWithFrame:CGRectMake(10 + 40, 25, 30, 30)];
    
    self.addButton.tag               = kAddButtonTag;
    self.addButton.layer.borderWidth = 1.f;
    
    [self.addButton setTitle:@"+"
                    forState:UIControlStateNormal];
    
    [self.addButton setTitleColor:[UIColor redColor]
                         forState:UIControlStateNormal];
    
    [self.addButton addTarget:self
                       action:@selector(buttonsEvent:)
             forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.addButton];
    
    // rolButton
    self.rolButton     = [[UIButton alloc] initWithFrame:CGRectMake(10 + 80, 25, 90, 30)];
    
    self.rolButton.tag               = kRolButtonTag;
    self.rolButton.layer.borderWidth = 1.f;
    
    [self.rolButton setTitle:@"rollBack"
                    forState:UIControlStateNormal];
    
    [self.rolButton setTitleColor:[UIColor redColor]
                         forState:UIControlStateNormal];
    
    [self.rolButton addTarget:self
                       action:@selector(buttonsEvent:)
             forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.rolButton];
}


@end

上一篇 下一篇

猜你喜欢

热点阅读