zoukankan      html  css  js  c++  java
  • iOS开发-命令模式

    命令模式算是设计模式中比较简单的,最常见的例子是工作任务安排下来进行编程,如果工作任务不需要完成,我们可以取消我们之前完成的代码,也可以理解为回滚撤销操作。这里面涉及到命令模式中的两个对象,一个是动作实现者,一个是行为请求者,我们可以将Boss理解为行为请求者,程序员理解为实现者,命令模式中我们通过调用者实现两者之间的解耦,生活中我们通过技术管理部门将老板和程序员隔离。我们有时候会遇到老板认为新版设计实现不如上一版,业务发生变化和开发效率的问题会随时进行任务的调整,虽然你有的时候很不情愿,但是还是会发生取消完成的任务,跟原来保持不变。

    基础知识

    先来看一下命令模式的UML类图:

    Client:客户端,命令发送者;

    Receiver:接收者,行为实现者;

    Command:命令基类,定义基础的命令方法;

    ConcreteCommand:命令子类,每个命令子类会关联一个Receiver,实现具体的任务;

    Invoker:调用者,负责执行打包过的命令对象;

    功能实现

    我们可以先来定义Command类:

    @protocol CommandProtocal <NSObject>
    
    @optional
    -(void)excute;
    @optional
    -(void)undo;
    
    @end
    
    @interface Command : NSObject<CommandProtocal>
    
    @end
    

    CarOnCommand类:

    @interface CarOnCommand(){
        Car *car;
    }
    
    @end
    
    @implementation CarOnCommand
    
    -(instancetype)initWithCar:(Car *)myCar{
        self=[super init];
        if (self) {
            car=myCar;
        }
        return self;
    }
    
    -(void)excute{
        [car on];
    }
    
    -(void)undo{
        [car off];
    }
    
    @end
    

    CarOffCommand实现:

    @interface CarOffCommand(){
        Car *car;
    }
    
    @end
    
    @implementation CarOffCommand
    
    -(instancetype)initWithCar:(Car *)myCar{
        self=[super init];
        if (self) {
            car=myCar;
        }
        return self;
    }
    
    -(void)excute{
        [car off];
    }
    
    -(void)undo{
        [car on];
    }
    
    @end
    

    DoorOpenCommand类:

    @interface  DoorOpenCommand(){
        Door  *myDoor;
    }
    @end
    
    @implementation DoorOpenCommand
    
    -(instancetype)initWithDoor:(Door *)door{
        self=[super init];
        if (self) {
            myDoor=door;
        }
        return self;
    }
    
    -(void)excute{
        [myDoor open];
    }
    
    -(void)undo{
        [myDoor shut];
    }
    
    @end
    DoorShutCommand
    @interface DoorShutCommand(){
        Door  *myDoor;
    }
    @end
    
    @implementation DoorShutCommand
    
    -(instancetype)initWithDoor:(Door *)door{
        self=[super init];
        if (self) {
            myDoor=door;
        }
        return self;
    }
    
    -(void)excute{
        [myDoor shut];
    }
    
    -(void)undo{
        [myDoor open];
    }
    
    @end
    

    这里需要提示一样,因为每个命令都会有撤销的功能,因为打开和关闭是两个单独的命令,不同对象的对象也是分开使用不同的命令,每个对象内部关于excute实现的过程会有不同~

    Invoker调用者的定义:

    @interface EleControl : NSObject
    
    -(instancetype)initWithCommandCount:(NSInteger)count;
    
    -(void)setupCommand:(NSInteger)index onCommand:(Command *)onCommand  offCommand:(Command *)offCommand;
    
    -(void)controlPressedOn:(NSInteger)index;
    
    -(void)controlPressedOff:(NSInteger)index;
    
    -(void)controlPressedUndo;
    
    @end
    

    Invoker的实现:

    @interface EleControl(){
        Command  *undoCommand;
    }
    
    @property (strong,nonatomic) NSMutableArray  *onCommands;
    
    @property  (strong,nonatomic) NSMutableArray *offCommands;
    
    @end
    
    @implementation EleControl
    
    -(instancetype)initWithCommandCount:(NSInteger)count{
        self=[super init];
        if (self) {
            for (NSInteger i=0; i<count; i++) {
                [self.onCommands addObject:[NSNull null]];
                [self.offCommands addObject:[NSNull null]];
            }
        }
        return self;
    }
    
    -(void)setupCommand:(NSInteger)index onCommand:(Command *)onCommand offCommand:(Command *)offCommand{
        self.onCommands[index]=onCommand;
        self.offCommands[index]=offCommand;
    }
    
    -(void)controlPressedOn:(NSInteger)index{
        Command *cmd=[self.onCommands objectAtIndex:index];
        [cmd excute];
        undoCommand=cmd;
    }
    
    -(void)controlPressedOff:(NSInteger)index{
        Command *cmd=[self.offCommands objectAtIndex:index];
        [cmd excute];
        undoCommand=cmd;
    }
    
    -(void)controlPressedUndo{
        [undoCommand undo];
    }
    
    #pragma mark getter and setter
    -(NSMutableArray *)onCommands{
        if (!_onCommands) {
            _onCommands=[[NSMutableArray alloc]init];
        }
        return _onCommands;
    }
    
    -(NSMutableArray *)offCommands{
        if (!_offCommands) {
            _offCommands=[[NSMutableArray alloc]init];
        }
        return _offCommands;
    }
    
    @end
    

     客户端调用:

        Car *car=[[Car alloc]init];
        Command *carOnCommand=[[CarOnCommand alloc]initWithCar:car];
        Command *carOffCommand=[[CarOffCommand alloc]initWithCar:car];
        
        Door  *door=[[Door alloc]init];
        Command  *doorOpenCommand=[[DoorOpenCommand alloc]initWithDoor:door];
        Command  *doorShutCommand=[[DoorShutCommand alloc]initWithDoor:door];
        
        EleControl *control=[[EleControl alloc]initWithCommandCount:2];
        [control setupCommand:0 onCommand:carOnCommand offCommand:carOffCommand];
        [control setupCommand:1 onCommand:doorOpenCommand offCommand:doorShutCommand];
        [control controlPressedOn:0];
        [control controlPressedOff:1];
        [control controlPressedUndo];
        NSLog(@"博客园-FlyElephant");
        NSLog(@"http://www.cnblogs.com/xiaofeixiang/");
    

    测试:

    关于命令模式实现的比较简单,NSUndoManger算是命令模式的典型应用,在一些线程池,工作队列中,我们只需要将具体的执行的任务包装成命令,当任务可以用的时候执行里面的execute方法,在日志和版本控制系统中回滚,我们会回到之前的稳定的版本,取代当前不能工作的版本也可以理解为命令模式在工程实践中的应用。

  • 相关阅读:
    在美国,一名 Uber 司机能赚多少?
    多名Uber司机被指刷单遭封号 一周薪水为0
    腾讯内推【腾讯工作机会内推】【腾讯社招内推】(长期有效)
    优步uber司机怎么注册不了?注册优步司机问题要点
    如何注册成为uber司机 快速成为优步司机网上注册流程攻略 2015最新
    Google AdSense的CPC点击单价超百度联盟(2014)
    非流动资产(财务报表解读)
    资产负债率
    流动资产(财务报表解读)
    UBER人民优步司机注册攻略
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/5108985.html
Copyright © 2011-2022 走看看