【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