【iOS笔记】软硬件通讯中的简单工厂模式

作者: joe浅蓝 | 来源:发表于2016-04-15 17:28 被阅读238次

写在前面


本人初入iOS不久,完全自学,以下内容如有不妥或不完善之处,还请各位指出,仅仅做个参考

关于工厂模式


因为平时在公司接触蓝牙和软硬件通讯比较多,这也是我接触过的第一种设计模式,在这里简单做一下记录,也分享给有用的人

从接触硬件通讯到现在,觉得工厂模式很适合这种多命令情况下的通讯以及命令处理,效率比较高,以下是命令工厂的一个简单例子(用Objective-C编写)

首先我们需要创建一个数据包的基类,包含了所有数据的公共部分,如命令字,长度等

并创建一个统一的StartDeal方法来让子类继承并处理数据

头文件和.m实现文件 如下

//
//  CMDBase.h
//  Factory
//
//  Created by Manager on 16/1/11.
//  Copyright © 2016年 EastHouse. All rights reserved.
//

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

@interface CMDBase : NSObject
{
@public
    //基类内容,包括命令字和需要处理的数据
    int CMD;
    Package *pkg;
}

//父类方法,用于子类继承并进行处理
- (void)startDeal;

@end
#import "CMDBase.h"

@implementation CMDBase

- (void)startDeal
{
    
}

@end

对于设备或硬件发送来的数据,我们最好做一个封装,这里就简单封装了一个Package类作为设备发送来的数据类

头文件和.m实现文件 如下

//
//  Package.h
//  Factory
//
//  Created by Manager on 16/1/11.
//  Copyright © 2016年 EastHouse. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Package : NSObject
{
    //数据类,根据自己的数据内容扩充
@public
    //命令字
    Byte m_CMD;
    //当前包号
    int m_PkgNumber;
    //数据存储
    NSData *m_data;
}

- (id)initWithPara:(NSData *)data;

- (id)init;

@end
#import "Package.h"

@implementation Package

- (id)initWithPara:(NSData *)data
{
    Byte *bytes = (Byte *)[data bytes];
    
    //根据数据位解析数据,假设命令字位于数据第二位,包号位于数据第三位
    m_CMD = bytes[2];
    m_PkgNumber = bytes[3];
    
    m_data = data;
    
    return self;
}

- (id)init
{
    m_CMD = 0x00;
    m_PkgNumber = -1;
    m_data = [[NSData alloc]init];
    
    return self;
}

@end

模拟几个子类,这里创建了三个子类

头文件和.m实现文件 如下

//
//  CMDOrder.h
//  Factory
//
//  Created by Manager on 16/1/11.
//  Copyright © 2016年 EastHouse. All rights reserved.
//

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

//默认创建了三个具体命令类
@interface CMD_B0 : CMDBase

@end

@interface CMD_B1 : CMDBase

@end

@interface CMD_B2 : CMDBase

@end
#import "CMDOrder.h"

@implementation CMD_B0

- (void)startDeal
{
    //收到B0命令字的处理
    NSLog(@"收到B0数据");
}

@end






@implementation CMD_B1

- (void)startDeal
{
    //收到B1命令字的处理
    
    switch (pkg->m_PkgNumber) {
        case 1:
            NSLog(@"收到B1数据,第一包");
            break;
        case 2:
            NSLog(@"收到B1数据,第二包");
            break;
        default:
            break;
    }
}

@end






@implementation CMD_B2

- (void)startDeal
{
    //收到B2命令字的处理
}

@end

接下来是最重要的部分,我们来创建我们的工厂类,主要用于生成对应的命令

头文件和.m实现文件 如下

//
//  CMDFactory.h
//  Factory
//
//  Created by Manager on 16/1/11.
//  Copyright © 2016年 EastHouse. All rights reserved.
//

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

@interface CMDFactory : NSObject

//查找并创建具体命令
+ (CMDBase *)findOrCreateCMD :(Byte)_CMD;

//创建具体命令
+ (CMDBase *)CreateCMD:(Byte)_CMD;

//移除所有命令,根据需要使用
+ (void)removeAllCMD;

@end
#import "CMDFactory.h"
#import "CMDOrder.h"

@implementation CMDFactory

static NSMutableArray *m_CMDs = nil;

+ (CMDBase *)findOrCreateCMD :(Byte)_CMD
{
    //初始化命令列表
    if(m_CMDs == nil)
        m_CMDs = [[NSMutableArray alloc]init];
    
    //如果命令存在直接返回
    for(CMDBase *_cmd in m_CMDs)
    {
        if(_cmd->CMD == _CMD)
            return _cmd;
    }
    
    //如果命令不存在创建新命令类
    CMDBase *newCMD = [self CreateCMD:_CMD];
    if(newCMD == nil)
        return nil;
    
    //新命令加入命令列表
    newCMD->CMD = _CMD;
    [m_CMDs addObject:newCMD];
    
    return newCMD;
}

+ (CMDBase *)CreateCMD:(Byte)_CMD
{
    //根据命令字创建具体的命令类
    switch (_CMD)
    {
        case 0xB0:
            return [[CMD_B0 alloc]init];
        case 0xB1:
            return [[CMD_B1 alloc]init];
        case 0xB2:
            return [[CMD_B2 alloc]init];
        default:
            return nil;
    }
}

+ (void)removeAllCMD
{
    [m_CMDs removeAllObjects];
}

@end

以上我们简单的工厂模式就创建完成了,具体的使用方法我这边写了一个例程,分别模拟了一个命令字中,存在单包数据或多包数据,内容位于viewcontroller中

头文件和.m实现文件 如下

//
//  ViewController.h
//  Factory
//
//  Created by Manager on 16/1/11.
//  Copyright © 2016年 EastHouse. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

- (IBAction)ButtonClicked:(id)sender;
- (IBAction)Button:(id)sender;

@end
#import "ViewController.h"
#import "Package.h"
#import "CMDFactory.h"

@interface ViewController ()

@end

@implementation ViewController

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

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

- (IBAction)ButtonClicked:(id)sender
{
    Byte datas[16] =
    {
        0xA6,0x27,0xB0,0x01,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00
    };
    NSData *data = [[NSData alloc]initWithBytes:datas length:16];
    
    Package *pkg = [[Package alloc]initWithPara:data];
    CMDBase *cmd = [CMDFactory findOrCreateCMD:pkg->m_CMD];
    if(cmd != nil)
    {
        cmd->pkg = pkg;
        
        //启动新线程处理数据,确保数据接收不会阻塞
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(dataReceived:) object:cmd];
        [thread start];
    }
}

- (IBAction)Button:(id)sender
{
    Byte datas1[16] =
    {
        0xA6,0x27,0xB1,0x01,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00
    };
    NSData *data1 = [[NSData alloc]initWithBytes:datas1 length:16];
    
    Package *pkg1 = [[Package alloc]initWithPara:data1];
    CMDBase *cmd1 = [CMDFactory findOrCreateCMD:pkg1->m_CMD];
    if(cmd1 != nil)
    {
        cmd1->pkg = pkg1;
        
        //启动新线程处理数据,确保数据接收不会阻塞
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(dataReceived:) object:cmd1];
        [thread start];
    }
    
    //简单延时,模拟两次收发数据
    [NSThread sleepForTimeInterval:1];
    
    Byte datas2[16] =
    {
        0xA6,0x27,0xB1,0x02,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00
    };
    NSData *data2 = [[NSData alloc]initWithBytes:datas2 length:16];
    
    Package *pkg2 = [[Package alloc]initWithPara:data2];
    CMDBase *cmd2 = [CMDFactory findOrCreateCMD:pkg2->m_CMD];
    if(cmd2 != nil)
    {
        cmd2->pkg = pkg2;
        
        //启动新线程处理数据,确保数据接收不会阻塞
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(dataReceived:) object:cmd2];
        [thread start];
    }
}

- (void)dataReceived:(CMDBase *)cmd
{
    //进行处理
    [cmd startDeal];
}

@end

以上就是全部代码了,都是自己手写的,希望可以帮助到有需要的人,也算给自己做个简单的记录,以后如果发现好的代码片,还会继续放到简书上,谢谢

Joe

相关文章

网友评论

    本文标题:【iOS笔记】软硬件通讯中的简单工厂模式

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