美文网首页
命令模式(Command Pattern)

命令模式(Command Pattern)

作者: iOS_学渣 | 来源:发表于2019-11-30 13:42 被阅读0次

命令模式:将请求封装成对象,以便使用不同的请求,队列,或日志,来参数化其他对象。命令模式也支持可撤销的操作。

命令模式是行为型模式之一。命令模式的核心就是将方法调用封装起来。通过封装方法调用,我们可以将运算块包装成形。调用运算块的对象不需要关心运算块是怎么运行的。只需要知道如何使用包装好的方法来完成它即可。

并且其中我们还可以做一些聪明的事,比如说记录日志,或者利用封装实现撤销操作。

这里封装的目的就是简化操作,比如说如何点亮一盏灯?作为核心开发人员需要了解控制和灯的相关接口和协议,普通人只需知道按下开关灯就亮了。命令模式就是将这些中间过程统一封装在命令中,然后只提供开/关命令。

下面是命令模式具体类图

命令模式

举个栗子(Head first上的栗子很有代表性,我不打算找其他的栗子,就把哪个智能遥控器的栗子搬过来,稍微简化下)

有个上游的厂商生产一款智能的遥控器,遥控器可以连接电灯,空调,电视或者更多其他的电子设备,遥控上面只有两种按钮一种是开启,一个是取消。每个按钮可以对应于任何设备的任何一个功能。
我们如何让遥控和设备对接。让它能控制对应的设备,并且可以方便后续扩展。
遥控器
第一排的左边按钮就开启电视,按第一排右边的按钮是还原。
第二排的左边按钮是调高空调的温度,右边的按钮是还原。
....

命令协议

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol Command <NSObject>

-(void)excute;

-(void)undo;

@end

NS_ASSUME_NONNULL_END

下游厂商的设备(电灯)

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Light : NSObject

-(void)on;

-(void)off;

@end

NS_ASSUME_NONNULL_END

下游厂商的设备(空调)

#import "AirCondition.h"
@interface AirCondition()

@property (nonatomic ,strong)NSMutableArray * temprature_in_type;

@end

@implementation AirCondition

-(instancetype)init {
    
    if (self = [super init]) {
        _temprature_in_type = [NSMutableArray arrayWithObjects:@(26),@(26),@(26),@(26), nil];
        _temperature = [_temprature_in_type[_type] integerValue];
    }return self;
}

-(void)changeType {
    
    if (_type == AirCondition_Dust_Removal){
        _type = AirCondition_Refrigeration;
        _temperature = [_temprature_in_type[_type] integerValue];
    } else {
        _type ++;
        _temperature = [_temprature_in_type[_type] integerValue];
    }
}


-(void)reduceTemperature {
    
    _temperature --;
    _temprature_in_type[_type] = @(_temperature);
}

-(void)increaseTemperature {
    
    _temperature ++;
    _temprature_in_type[_type] = @(_temperature);
}

-(void)on {
    
    NSString * type ;
    switch (_type) {
        case AirCondition_Refrigeration:
            type = @"制冷模式";
            break;
        case AirCondition_Heating:
            type = @"制热模式";
            break;
        case AirCondition_Dehumidification:
            type = @"除湿模式";
            break;
        case AirCondition_Dust_Removal:
            type = @"除尘模式";
            break;
    }
    NSLog(@"空调开启了,当前模式为%@,设定温度为%ld℃",type,_temperature);
}

-(void)off {
    
    NSLog(@"空调关闭了");
}
@end

灯泡亮起的命令

#import "LightOnCommand.h"
#import "Light.h"
@interface LightOnCommand ()

@property (nonatomic ,strong)Light * light;

@end

@implementation LightOnCommand

-(instancetype)initWithLight:(Light *)light {
    
    if (self = [super init]) {
        
        _light = light;
    }return self;
}

-(void)excute {
    
    [_light on];
}

- (void)undo {
    
    [_light off];
}

@end

灯泡熄灭的命令

#import "LightOffCommand.h"
#import "Light.h"

@interface LightOffCommand ()

@property (nonatomic ,strong)Light * light;

@end

@implementation LightOffCommand

-(instancetype)initWithLight:(Light *)light {
    
    if (self = [super init]) {
        
        _light = light;
    }return self;
}

-(void)excute {
    
    [_light off];
}

- (void)undo {
    
    [_light on];
}

@end

空调开启的命令

#import "AirConditionOnCommand.h"
#import "AirCondition.h"
@interface AirConditionOnCommand ()

@property (nonatomic ,strong)AirCondition * condition;

@end
@implementation AirConditionOnCommand

-(instancetype)initWithAirCondition:(AirCondition *)condition {
    
    if (self = [super init]) {
        
        _condition = condition;
    }return self;
}

- (void)excute {
    
    [_condition on];
}

- (void)undo {
    
    [_condition off];
}

@end

空调关闭的命令

#import "AirConditionOffCommand.h"
#import "AirCondition.h"

@interface AirConditionOffCommand ()

@property (nonatomic ,strong)AirCondition * condition;
@end

@implementation AirConditionOffCommand

-(instancetype)initWithAirCondition:(AirCondition *)condition {
    if (self = [super init]) {
        _condition = condition;
    }return self;
}

- (void)excute {
    
    [_condition off];
}

- (void)undo {
    
    [_condition on];
}

@end

空调状态切换的命令

#import "AirConditionChangeTypeCommand.h"
#import "AirCondition.h"
@interface AirConditionChangeTypeCommand ()

@property (nonatomic ,strong)AirCondition * condition;
@property (nonatomic ,assign)AirConditionType type;

@end
@implementation AirConditionChangeTypeCommand


-(instancetype)initWithAirCondition:(AirCondition *)condition {
    
    if (self = [super init]) {
        
        _condition = condition;
    }return self;
}


- (void)excute {
    
    _type = _condition.type;
    [_condition changeType];
}

- (void)undo {
    
    _condition.type = _type;
}

@end

空调温度降低的命令

#import "AirConditionReduceTemperatureCommand.h"
#import "AirCondition.h"
@interface AirConditionReduceTemperatureCommand ()

@property (nonatomic ,strong)AirCondition * condition;

@end
@implementation AirConditionReduceTemperatureCommand

-(instancetype)initWithAirCondition:(AirCondition *)condition {
    if (self = [super init]) {
        
        _condition = condition;
    }return self;
}


- (void)excute {
    
    [_condition reduceTemperature];
}

- (void)undo {
    
    [_condition increaseTemperature];
}


@end

空调增温的命令

#import "AirConditionIncreaseTemperatureCommand.h"
#import "AirCondition.h"


@interface AirConditionIncreaseTemperatureCommand()
@property (nonatomic ,strong)AirCondition * condition;
@end
@implementation AirConditionIncreaseTemperatureCommand

-(instancetype)initWithAirCondition:(AirCondition *)condition {
    if (self = [super init]) {
        _condition = condition;
    }return self;
}

- (void)excute {
    
    [_condition increaseTemperature];
}

- (void)undo {
    
    [_condition reduceTemperature];
}

@end

调用者(Invoker)这里的调用者就是遥控器

#import "RemoteControl.h"
#import "NoCommand.h"
@interface RemoteControl ()

@property (nonatomic ,strong)NSMutableArray * onCommands;
@property (nonatomic ,strong)NSMutableArray * offCommands;
@property (nonatomic ,strong)NSMutableArray * undoCommands;

@end

@implementation RemoteControl

-(instancetype)initWithControlSize:(NSInteger)size {
    
    if (self = [super init]) {
        
        _onCommands = [NSMutableArray arrayWithCapacity:size];
        _offCommands = [NSMutableArray arrayWithCapacity:size];
        _undoCommands = [NSMutableArray array];
        NoCommand * command = [[NoCommand alloc] init];
        for (int i = 0 ; i < size ; i++) {
            _onCommands[i] = command;
            _offCommands[i] = command;
        }
    }return self;
}

-(void)setOnCommand:(id<Command>)onCommand offCommand:(id<Command>)offCommand atIndex:(NSInteger)index {
    
    _onCommands[index] = onCommand;
    _offCommands[index] = offCommand;
}

-(void)onButtonPushedAtIndex:(NSInteger)index {
    
    if (index > _onCommands.count - 1) return ;
    if (index < 0) return;
    id<Command> command = _onCommands[index];
    [command excute];
    [_undoCommands addObject:command];
}

-(void)offButtonPushedAtIndex:(NSInteger)index {
    
    if (index > _onCommands.count - 1) return ;
    if (index < 0) return;
    id<Command> command = _offCommands[index];
    [command excute];
    [_undoCommands addObject:command];
}

-(void)undoButtonPushed {
    
    if (_undoCommands.count <= 0) return ;
    id<Command> command = _undoCommands.lastObject;
    [_undoCommands removeLastObject];
    [command undo];
    
}

@end

具体使用

#import <Foundation/Foundation.h>
#import "LightOnCommand.h"
#import "LightOffCommand.h"
#import "AirConditionOnCommand.h"
#import "AirConditionOffCommand.h"
#import "AirConditionChangeTypeCommand.h"
#import "AirConditionReduceTemperatureCommand.h"
#import "AirConditionIncreaseTemperatureCommand.h"
#import "RemoteControl.h"

#import "Light.h"
#import "AirCondition.h"

//客户
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //接收者
        Light * light = [[Light alloc] init];
        AirCondition * condition = [[AirCondition alloc] init];
        //命令
        //开关
        LightOnCommand * lightOn = [[LightOnCommand alloc] initWithLight:light];
        LightOffCommand * lightOff = [[LightOffCommand alloc] initWithLight:light];
        
        //空调开关
        AirConditionOnCommand * airOn = [[AirConditionOnCommand alloc] initWithAirCondition:condition];
        AirConditionOffCommand * airOff = [[AirConditionOffCommand alloc] initWithAirCondition:condition];
        
        //空调控制
        AirConditionChangeTypeCommand * airType = [[AirConditionChangeTypeCommand alloc] initWithAirCondition:condition];
        //空调温度
        AirConditionReduceTemperatureCommand * airReduTemp = [[AirConditionReduceTemperatureCommand alloc] initWithAirCondition:condition];
        AirConditionIncreaseTemperatureCommand * airIncrTemp = [[AirConditionIncreaseTemperatureCommand alloc] initWithAirCondition:condition];
        
        //调用者
        RemoteControl * control = [[RemoteControl alloc] initWithControlSize:5];
        
        //添加command
        [control setOnCommand:lightOn offCommand:lightOff atIndex:0];
        [control setOnCommand:airOn offCommand:airOff atIndex:1];
        [control setOnCommand:airType offCommand:airOff atIndex:2];
        [control setOnCommand:airReduTemp offCommand:airOff atIndex:3];
        [control setOnCommand:airIncrTemp offCommand:airOff atIndex:4];
        
        [control onButtonPushedAtIndex:2];
        [control onButtonPushedAtIndex:1];
        
    }
    return 0;
}

优点

将调用命令的对象和命令解耦
很容易添加新的命令
很容易取消旧的命令
可以将多个命令组合成一个命令

缺点

会导致系统具有过多的命令类

相关文章

  • 命令模式(Command Pattern)

    命令模式 命令模式(Command Pattern)又称为行动(Action)模式或交易(Transaction)...

  • 命令模式

    命令模式(Command Pattern) 定义 Encapsulate a request as an obje...

  • 设计模式[18]-命令模式-Comand Pattern

    1.命令模式简介 命令模式(Command Pattern)模式是是行为型(Behavioral)设计模式,将一个...

  • 命令模式(Command Pattern)

    命令模式:将请求封装成对象,以便使用不同的请求,队列,或日志,来参数化其他对象。命令模式也支持可撤销的操作。 命令...

  • 命令模式(Command Pattern)

    命令模式 意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支...

  • Command模式(命令模式)

    命令模式(Command Pattern)是一种数据驱动的设计模式。Command有时也被成为事件(event)。...

  • 行为型-Command

    命令模式的原理解读 命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》...

  • 设计模式-命令模式

    命令模式 介绍: 模式模式(Command Pattern),是行为型设计模式之一。命令模式相对于其他的设计模式来...

  • Swift设计模式——命令模式

    什么是命令模式? 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令...

  • Android 架构师之路11 设计模式之命令模式

    Android 架构师之路 目录 1、命令模式概念 1.1 介绍 命令模式(Command Pattern)是一种...

网友评论

      本文标题:命令模式(Command Pattern)

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