实例讲解设计模式中的命令模式在iOS App开发中的运用

命令模式封装一个请求或行为作为一个对象。封装的请求比原的更加灵活,可以在对象之间传递,储存,动态修改,或放入一个队列。

那么让我们简要的说一下命令模式的特点。

  • 它能比较容易地设计一个命令队列;
  • 在需要的情况下,可以较容易地将命令记入日志;
  • 允许接收请求地一方决定是否要否决请求;
  • 可以容易地实现对请求地撤销和重做;
  • 由于加进新地具体命令类不影响其他的类,因此增加新的具体命令类很容易;
  • 把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。

下面给出基本的类结构图:

上面这张图是命令模式的类结构的基本图。其实从这张图中还可以扩展出很多,细节就不说了,给大家留一些想象的空间,呵呵!

还是老规矩,下面给出实例:

Objective-C 示例:

Command:

代码如下:

//
//  NimoCommand.h
//  CommandDemo
//
 
#import <Foundation/Foundation.h>
 
@protocol NimoCommand <NSObject>
 
- (void)execute;
 
@end

ConcreteCommand:

代码如下:

//
//  NimoConcreteCommand.h
//  CommandDemo
//
#import <Foundation/Foundation.h>
#import "NimoCommand.h"
@class NimoReceiver;
 
@interface NimoConcreteCommand : NSObject <NimoCommand>
 
@property (nonatomic) NimoReceiver *receiver;
 
- (id)initWithReceiver:(NimoReceiver *)receiver;
 
@end

代码如下:

//
//  NimoConcreteCommand.m
//  CommandDemo
//
 
#import "NimoConcreteCommand.h"
#import "NimoReceiver.h"
 
 
@implementation NimoConcreteCommand
 
- (void)execute
{
    [_receiver action];
}
 
- (id)initWithReceiver:(NimoReceiver *)receiver
{
    if (self = [super init]) {
        _receiver = receiver;
    }
    
    return self;
}
 
@end

Receiver:

代码如下:

//
//  NimoReceiver.h
//  CommandDemo
//

#import <Foundation/Foundation.h>
 
@interface NimoReceiver : NSObject
 
- (void)action;
 
@end

代码如下:

//
//  NimoReceiver.m
//  CommandDemo
//

#import "NimoReceiver.h"
 
@implementation NimoReceiver
 
- (void)action
{
    NSLog(@"实际执行");
}
 
@end

Invoker:

代码如下:

//
//  NimoInvoker.h
//  CommandDemo
//
 
#import <Foundation/Foundation.h>
#import "NimoCommand.h"
 
@interface NimoInvoker : NSObject
 
@property (nonatomic, weak) id<NimoCommand> command;
 
- (void)executeCommand;
 
@end

代码如下:

//
//  NimoInvoker.m
//  CommandDemo
//
 
#import "NimoInvoker.h"
 
 
@implementation NimoInvoker
 
- (void)executeCommand
{
    [_command execute];
}
 
@end

Client:

代码如下:

//
//  main.m
//  CommandDemo
//

#import <Foundation/Foundation.h>
#import "NimoReceiver.h"
#import "NimoInvoker.h"
#import "NimoConcreteCommand.h"
 
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        NimoReceiver *receiver = [[NimoReceiver alloc] init];
        NimoConcreteCommand *command = [[NimoConcreteCommand alloc] initWithReceiver:receiver];
        
        NimoInvoker *invoker = [[NimoInvoker alloc] init];
        invoker.command = command;
        [invoker executeCommand];
        
    }
    return 0;
}

Running:

2015-08-13 22:49:56.412 CommandDemo[1385:43303] 实际执行

Cocoa Touch框架中的命令模式:

NSInvocation对象

如下示例,Client没有直接调用Receiver的方法,而是用NSInvocation对象封装了运行时库向Receiver发送执行消息所需的所有必要信息,这里的NSInvocation对象类似于上文中的ConcreteCommand对象。

Receiver:

代码如下:

//
//  NimoReceiver.h
//  InvocationDemo
//

#import <Foundation/Foundation.h>
 
@interface NimoReceiver : NSObject
 
- (int)printWithName:(NSString *)name gender:(NSString *)gender age:(int)age;
 
@end

代码如下:

//
//  NimoReceiver.m
//  InvocationDemo
//

#import "NimoReceiver.h"
 
@implementation NimoReceiver
 
- (int)printWithName:(NSString *)name gender:(NSString *)gender age:(int)age
{
    NSLog(@"My name is %@, %@, %d years old.", name, gender, age);
    return 119;
}
 
@end

Client:

代码如下:

//
//  main.m
//  InvocationDemo
//

#import <Foundation/Foundation.h>
#import "NimoReceiver.h"
 
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //用Receiver的实例创建NSInvocation对象,并把Receiver的action作为选择器
        NimoReceiver *receiver = [[NimoReceiver alloc] init];
        NSString *name = @"Lee";
        NSString *gender = @"male";
        int age = 28;
        SEL sel = @selector(printWithName:gender:age:);
        NSMethodSignature *methodSignature = [[receiver class] instanceMethodSignatureForSelector:sel];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
        [invocation setTarget:receiver];
        [invocation setSelector:sel];
        [invocation setArgument:&name atIndex:2];
        [invocation setArgument:&gender atIndex:3];
        [invocation setArgument:&age atIndex:4];
        [invocation retainArguments];
        [invocation invoke]; //通过调用NSInvocation对象的invoke方法,完成对Receiver中action的调用
        
        int returnValue = 0;
        [invocation getReturnValue:&returnValue];
        
        NSLog(@"returnValue: %d", returnValue);
    }
    return 0;
}

Running:

2015-08-14 13:37:44.162 InvocationDemo[1049:36632] My name is Lee, male, 28 years old.
2015-08-14 13:37:44.164 InvocationDemo[1049:36632] returnValue: 119

其实,单从类关系图中可以简单的看出,命令模式其实是把需求(Invoker)和具体实现(Receiver)通过命令层(Command)进行了解耦。具体实现过程根据不同的命令进行了区分。

(0)

相关推荐

  • 详解iOS应用的设计模式开发中Mediator中介者模式的使用

    何为中介者模式? 面向对象的设计鼓励把行为分散到不同对象中,这种分散可能导致对象之间的相互关联.在最糟糕的情况下,所有对象都彼此了解并相互操作. 虽然把行为分散到不同对象增强了可复用性,但是增加的相互关联又减少了获得的益处.增加的关联使得对象很难或不能在不依赖其他对象的情况下工作.应用程序的整体行为可能难以进行任何重大修改,因为行为分布于许多对象.于是结果可能是创建越来越多的子类,以支持应用程序中的任何新行为. 中介者模式:用一个对象来封装一系列对象的交互方式.中介者使各对象不需要显式地相互引用

  • IOS设计模式之组合设计模式

    Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和ViewGroup类的使用.在android UI设计,几乎所有的widget和布局类都依靠这两个类. 组合模式,Composite Pattern,是一个非常巧妙的模式.几乎所有的面向对象系统都应用到了组合模式. 通过本文将让你学会软件开发中的"何为树形结构"."何为组合模式"."组合模式可以解决的问题"等相关知识. 内容大纲: 1.树形结构 2.组合模式 3.编写文件

  • 使用设计模式中的Singleton单例模式来开发iOS应用程序

    单例设计模式确切的说就是一个类只有一个实例,有一个全局的接口来访问这个实例.当第一次载入的时候,它通常使用延时加载的方法创建单一实例. 提示:苹果大量的使用了这种方法.例子:[NSUserDefaults standerUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager] 都返回一个单一对象. 你可能想知道你为什么要关心一个类有多个的实例.代码

  • iOS应用开发中运用设计模式中的组合模式的实例解析

    何为组合模式?     组合模式让我们可以把相同基类型的对象组合到树状结构中,其中父节点包含同类型的子节点.换句话说,这种树状结构形成"部分--整体"的层次结构.什么是"部分--整体"的层次结构呢?它是既包含对象的组合又包含叶节点的单个对象的一种层次结构.每个组合体包含的其他节点,可以是叶节点或者其他组合体.这种关系在这个层次结构中递归重复.因为每个组合或叶节点有相同的基类型,同样的操作可应用于它们中的每一个,而不必在客户端作类型检查.客户端对组合与叶节点进行操作时

  • IOS观察者设计模式

    什么是观察者模式?我们先打个比方,这就像你订报纸.比如你想知道美国最近放生了些新闻,你可能会订阅一份美国周刊,然后一旦美国有了新的故事,美国周刊就发一刊,并邮寄给你,当你收到这份报刊,然后你就能够了解美国最新的动态.其实这就是观察者模式,A对B的变化感兴趣,就注册为B的观察者,当B发生变化时通知A,告知B发生了变化.这是一种非常典型的观察者的用法,我把这种使用方法叫做经典观察者模式.当然与之相对的还有另外一种观察者模式--广义观察者模式. 从经典的角度看,观察者模式是一种通知变化的模式,一般认为

  • iOS应用运用设计模式中的Strategy策略模式的开发实例

    在写程序的时候,我们经常会碰到这样的场景:把一堆算法塞到同一段代码中,然后使用if-else或switch-case条件语句来决定要使用哪个算法?这些算法可能是一堆相似的类函数或方法,用以解决相关的问题.比如,一个验证输入数据的例程,数据本身可以是任何数据类型(如NSString.CGFloat等),每种数据类型需要不同的验证算法.如果能把每个算法封装成一个对象,那么就能消除根据数据类型决定使用什么算法的一堆if-else或switch-case语句. 我们把相关算法分离为不同的类,称为策略模式

  • iOS App开发中使用设计模式中的单例模式的实例解析

    一.单例的作用 顾名思义,单例,即是在整个项目中,这个类的对象只能被初始化一次.它的这种特性,可以广泛应用于某些需要全局共享的资源中,比如管理类,引擎类,也可以通过单例来实现传值.UIApplication.NSUserDefaults等都是IOS中的系统单例. 二.单例模式的两种写法 1,常用写法 #import "LGManagerCenter.h" static LGManagerCenter *managerCenter; @implementation LGManagerCe

  • 深入解析iOS应用开发中对设计模式中的桥接模式的使用

    引言 在项目开发中,我们会遇到这样的一种场景:某些类型由于自身的逻辑,往往具有两个或多个维度的变化,比如说大话设计模式书中所说的手机,它有两个变化的维度:一是手机的品牌,可能有三星.苹果等:二是手机上的软件,可能有QQ.微信等.如何应对这种"多维度的变化"?怎样利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就是本章桥接模式所要解决的问题. 何为桥接模式? 桥接模式的目的是把抽象层次结构从其实现中分离出来,使其能够独立变更.抽象层定义了供客户端使

  • iOS应用设计模式开发中对简单工厂和工厂方法模式的运用

    简单工厂模式 正如此模式的名称一样,简单工厂模式基本上是所有设计模式里最简单的一种,类与类之间的关系一目了然.这次我就用很多地方经常举的例子--计算器,来说明这个模式.首先给大家展示一下类之间的结构图: 通过这张结构图,可以清晰的看到,加法类.减法类.乘法类.除法类继承自运算类,简单工厂类依赖于运算类的实例化来实现相应的运算功能,好的,看起来并不复杂,让我们直接展示一下代码吧(鉴于目前点点不支持Objective C的代码高亮,所以就直接写啦,尽量保持整齐吧.另,为了照顾像我一样基础不是很好的同

  • 实例讲解如何在iOS应用开发中使用设计模式中的代理模式

    代理模式是OC中一种常见的设计模式,那么什么是代理模式呢?举个栗子,假设你是一个日发货量过万的淘宝卖家(A),但是每天的派件不可能你本人或者让你的员工去派件,因此你发布了一条信息(B),上面注明各种要求,各大快递公司看到有那么大的利益纷纷上门沟通,最后你选择了一件快递公司(C).那么在上面的例子中,我们即是委托人,发布的信息即协议(protocol),上面规定了派件人需要完成的事,而最后选择的快递公司也就是代理人(delegate),代理我们去派件. 类图: 根据以上类图,可以知道在代理模式中的

随机推荐