iOS学习开发iOS漫步者原理篇

设计模式--命令模式(iOS)

2018-04-16  本文已影响28人  留个念想给昨天
命令模式UML图

1、命令模式-定义

第一点:将一个请求封装成为一个对象,从而让用户使用不同的请求将客户端参数化
第二点:对请求排队或者纪录请求日志,以及支持撤销操作
说白了:让我们程序扩展性更加好了,耦合降低了

2、命令模式-应用场景?

当需要将方法调用包装成一个对象,以延时方法调用,或者让其他组件在对其内部实现细节不了解的情况下进行调用的时候可以使用命令模式

场景一:应用程序支持撤销和恢复
场景二:记录请求日志,当系统故障这些命令可以重新被执行
场景三:想用对象参数化一个动作以执行操作,并且用不同命令对象来替换回调函数

3、命令模式-角色划分?——>有很多变种(演示变种)

行为设计模式中一种

角色一:接收者(Receiver作用:负责具体的功能实现->具体实现细节)
角色二:命令接口(协议)(Command:命令抽象)
角色三:具体的命令(ConcreteCmmand:具体的命令,作用:负责调用接收者逻辑方法,行为方法)
角色四:请求者角色(Invoker:调用执行命令)
角色五:客户端

4、实现一个让屏幕变暗、变亮、撤销的功能

可以先下载Demo
效果图如下

4.1 接收者

接收者(Receiver作用:负责具体的功能实现->具体实现细节

伪代码
#接收者可想而之是屏幕的view
所以要建一个属性接收屏幕的view

#还包含具体的功能实现
1、变暗的方法
2、变亮的方法

#import <UIKit/UIKit.h>

@interface Receiver : NSObject {
    CGFloat _white;  // 白的
    CGFloat _alpha;  // 透明度
}

// 接收者的view
@property (nonatomic, strong) UIView *receiverView;

// 具体的功能-----变暗的接口
- (void)mackeDarker:(CGFloat)pamameter;

// 具体的功能-----变亮的接口
- (void)mackeLighter:(CGFloat)pamameter;

@end

#import "Receiver.h"

@implementation Receiver

- (void)setReceiverView:(UIView *)receiverView {
    // 获取数值
    _receiverView = receiverView;
    UIColor *color = _receiverView.backgroundColor;
    
    [color getWhite:&_white alpha:&_alpha];
}

// 变暗的接口
- (void)mackeDarker:(CGFloat)pamameter {
    _white -= pamameter;
    // 设置取值范围
    _white = MAX(0, _white);
    
    // 设置背景色
    _receiverView.backgroundColor = [UIColor colorWithWhite:_white alpha:_alpha];
}

// 变亮的接口
- (void)mackeLighter:(CGFloat)pamameter {
    _white += pamameter;
    // 设置取值范围
    _white = MIN(1, _white);
    
    // 设置背景色
    _receiverView.backgroundColor = [UIColor colorWithWhite:_white alpha:_alpha];
}
@end

这样就可以直接通过调用Receiver,来实现屏幕变亮和变暗的功能,就是不能实现回退的功能

4.2 命令接口(协议)

命令接口包括执行命令和撤销命令

#import <Foundation/Foundation.h>

@protocol CommandProtocol <NSObject>

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

// 撤销命令
- (void)backExcute;

@end

4.3 具体的命令

***具体的命令,作用:负责调用接收者逻辑方法,行为方法
***通过UML图可以看出:要关联接收者以便调用接收者逻辑方法和行为方法,实现CommandProtocol的协议
这里就用两个类:
DarkerCommandLighterCommand两个类
一个执行变暗的方法,一个执行变亮的方法

这里有个注意点,以DarkerCommand为例来说明:这里excute的方法为receiver执行变暗的方法,而撤销方法就为receiver执行变亮的方法

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

@interface DarkerCommand : NSObject <CommandProtocol>

// 绑定接收器
- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter;

@end

#import "DarkerCommand.h"

@interface DarkerCommand ()
@property (nonatomic, strong) Receiver *receiver;
@property (nonatomic, assign) 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 mackeDarker:self.paramter];
}

// 撤销命令
- (void)backExcute {
    [self.receiver mackeLighter:self.paramter];
}

@end
#import <Foundation/Foundation.h>
#import "CommandProtocol.h"
#import "Receiver.h"

@interface LighterCommand : NSObject <CommandProtocol>

// 绑定接收器
- (instancetype)initWithReceiver:(Receiver *)receiver paramter:(CGFloat)paramter;

@end
#import "LighterCommand.h"

@interface LighterCommand ()
@property (nonatomic, strong) Receiver *receiver;
@property (nonatomic, assign) CGFloat paramter;

@end

@implementation LighterCommand

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

// 执行命令
- (void)excute {
    [self.receiver mackeLighter:self.paramter];
}

// 撤销命令
- (void)backExcute {
    [self.receiver mackeDarker:self.paramter];
}

@end

4.4 请求者

请求者角色(Invoker):调用执行命令,并将命令加入数组,然后做撤销操作

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

@interface Invoker : NSObject

+ (instancetype)sharedInstance;

// 回退指令
- (void)goBack;

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


#import "Invoker.h"
@interface Invoker ()
@property (nonatomic, strong) NSMutableArray *array;  // 存储操作的
@end

@implementation Invoker

+ (instancetype)sharedInstance
{
    static Invoker *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        sharedInstance = [[self alloc] init];
        sharedInstance.array = [NSMutableArray array];
        
    });
    return sharedInstance;
}

// 回退指令
- (void)goBack {
    // 1.获取数组中的最后一个操作
    id <CommandProtocol> command = self.array.lastObject;
    
    // 2.操作调用,撤销的步骤
    [command backExcute];
    
    // 3.删除最后操作
    [self.array removeLastObject];
}

// 添加操作指令
- (void)addAndExcute:(id <CommandProtocol>)command {
    // 1.把操作添加到数组
    [self.array addObject:command];
    
    // 2.让操作调用实现的协议方法
    [command excute];
}
@end

4.5 测试

//1.接收器
self.receiver = [[Receiver alloc] init];
self.receiver.receiverView = self.view;

//2. 变暗
DarkerCommand *command = [[DarkerCommand alloc] initWithReceiver:self.receiver paramter:0.1];
[[Invoker sharedInstance] addAndExcute:command];

//3. 变亮
LighterCommand *command = [[LighterCommand alloc] initWithReceiver:self.receiver paramter:0.1];
[[Invoker sharedInstance] addAndExcute:command];

//4. 回退操作
[[Invoker sharedInstance] goBack];

有兴趣的可以下载Demo了解一下

写在最后:

 希望这篇文章对您有帮助,最好就是实操一边,这样才能理解更深入。
 当然如果您发现有可以优化的地方,希望您能慷慨的提出来。
 最后祝您工作愉快!
上一篇 下一篇

猜你喜欢

热点阅读