写在前面
本人初入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
网友评论