命令模式

在这里插入图片描述

类构成
对具体的某一类行为进行参数化
达到解耦,降低代码重合度
命令
命令A
执行
具体任务A
取消
将Block设置为nil,则不进行回调。即取消了
完成
异步回到主队列,防止多线程循环引用
执行完毕,从队列中进行移除
命令B
执行
具体任务B
取消
将Block设置为nil,则不进行回调。即取消了
完成
异步回到主队列,防止多线程循环引用
执行完毕,从队列中进行移除
命令管理者
进行命令的管理
执行命令
取消指令

场景
(某金融项目)点赞、评论、转发。多处散落
UGC、PGC列表页和详情页穿插的重复代码
使用设计模式对其行为封装成具体的子类(也需要特定的管理者)

注意点
命令管理者
单例《如果异步操作后,同一命令多次被调用,防止重复执行指令》
取消命令的执行,从容器中进行移除。命令执行完成也需要进行移除
命令
相当于具体的小任务

代码片段
Command(命令)
@class Command;
typedef void(^CommandCompletionCallBack)(Command* cmd);

@interface Command : NSObject
//命令执行完成
@property (nonatomic, copy) CommandCompletionCallBack completion;

  • (void)execute;
  • (void)cancel;
  • (void)done;

@end
#import “Command.h”
#import “CommandManager.h”
@implementation Command

  • (void)execute{

    //override to subclass;

    [self done];
    }

  • (void)cancel{
    //将block设置为nil
    self.completion = nil;
    }

  • (void)done
    { //异步回到主队列,防止多线程时候产生循环引用
    dispatch_async(dispatch_get_main_queue(), ^{

      if (_completion) {
          _completion(self);
      }
      
      //释放
      self.completion = nil;
      //命令执行完成了。进行移除
      [[CommandManager sharedInstance].arrayCommands removeObject:self];
    

    });
    }

@end
抽象子类
CommandA

@implementation CommandA

  • (void)execute{
    NSLog(@“CommandA - 转发”);

    [super execute];
    }
    CommandB
    @implementation CommandB

  • (void)execute{
    NSLog(@“CommandB - 点赞”);
    [super execute];
    }

@end
CommandManager(命令管理器)
#import “Command.h”
@interface CommandManager : NSObject
// 命令管理容器
@property (nonatomic, strong) NSMutableArray <Command*> *arrayCommands;

// 命令管理者以单例方式呈现

  • (instancetype)sharedInstance;

// 执行命令

  • (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion;

// 取消命令

  • (void)cancelCommand:(Command *)cmd;

@end
#import “CommandManager.h”

@implementation CommandManager

// 命令管理者以单例方式呈现

  • (instancetype)sharedInstance
    {
    static CommandManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    instance = [[super allocWithZone:NULL] init];
    });
    return instance;
    }

// 【必不可少】

  • (id)allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance];
    }

// 【必不可少】

  • (id)copyWithZone:(nullable NSZone *)zone{
    return self;
    }

// 初始化方法

  • (id)init
    {
    self = [super init];
    if (self) {
    // 初始化命令容器
    _arrayCommands = [NSMutableArray array];
    }
    return self;
    }
  • (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion
    {
    if (cmd) {
    // 如果命令正在执行不做处理,否则添加并执行命令
    if (![self _isExecutingCommand:cmd]) {
    // 添加到命令容器当中
    [[[self sharedInstance] arrayCommands] addObject:cmd];
    // 设置命令执行完成的回调
    cmd.completion = completion;
    //执行命令
    [cmd execute];
    }
    }
    }

// 取消命令

  • (void)cancelCommand:(Command *)cmd
    {
    if (cmd) {
    // 从命令容器当中移除
    [[[self sharedInstance] arrayCommands] removeObject:cmd];
    // 取消命令执行
    [cmd cancel];
    }
    }

// 判断当前命令是否正在执行

  • (BOOL)_isExecutingCommand:(Command *)cmd
    {
    if (cmd) {
    NSArray *cmds = [[self sharedInstance] arrayCommands];
    for (Command *aCmd in cmds) {
    // 当前命令正在执行
    if (cmd == aCmd) {
    return YES;
    }
    }
    }
    return NO;
    }

@end

调用
@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    Command * commandA = [[CommandA alloc]init];
    //举例调用入口B
    [CommandManager executeCommand:commandA completion:^(Command *cmd) {
    NSLog(@"_commandA = %@",cmd);
    }];
    }

  • (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    Command * commandB = [[CommandB alloc]init];
    //举例:调用入口B
    [CommandManager executeCommand:commandB completion:^(Command *cmd) {
    NSLog(@"_commandB = %@",cmd);
    }];
    }

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值