这里使用的是简单工厂模式。
简单工厂模式的定义:
简单工厂模式是属于创建型模式,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。
简单工厂模式的使用:
我们在UITableView的协议方法里经常可以看到这样代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row==0) {
EEvaluteUserInfoTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"EEvaluteUserInfoTableViewCell"];
return cell;
}
else if(indexPath.row==1){
EEvaluteTipLineTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"EEvaluteTipLineTableViewCell"];
return cell;
}
else {
EEvaluteTextViewTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"EEvaluteTextViewTableViewCell"];
return cell;
}
}
更有甚者可以达到十几种以上的cell存在(比如聊天界面),这样的话相关类的代码量就会变得十分庞大。
这种情况我们就可以使用简单工厂模式来搭建。
解决方案:
我们还是以聊天界面为例:
首先我们创建一个批量获取界面模型的工厂,用来根据不同的数据模型返回不同的界面模型:
#import "KKMessageCellFactory.h"
@implementation KKMessageCellFactory
- (KKBaseMessageCell *)getMessageCellFromModel:(KKBaseMessageModel *)model forTableView:(UITableView *)tableView {
NSString *cellName = [model cellName];
NSString *identifier = [NSString stringWithFormat:@"%@_Id",cellName];
KKBaseMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(!cell) {
[tableView registerClass:NSClassFromString(cellName) forCellReuseIdentifier:identifier];
cell = [tableView dequeueReusableCellWithIdentifier:identifier];
}
return cell;
}
@end
然后我们创建两个基类,一个界面基类,一个数据模型的基类。基类提供方法由子类重写实现。
@interface KKBaseMessageCell : UITableViewCell
#cell赋值
- (void)setDataModel:(KKBaseMessageModel *)model;
@end
@interface KKBaseMessageModel : NSObject
// model对应的cell的类名
- (NSString *)cellName;
// 数据对应的界面元素的尺寸。
- (CGSize)dataSizeForMessage;
@end
接下来我们就可以创建子类了。
创建KKTextMessageModel,KKImageMessageModel,KKVideoMessageModel分别对应KKTextMessageCell,KKImageMessageCell,KKVideoMessageCell。
model子类里面实现方法:
@implementation KKTextMessageModel
- (NSString *)cellName {
return @"KKTextMessageCell";
}
- (CGSize)dataSizeForMessage {
return CGSizeMake([UIScreen mainScreen].bounds.size.width, 50);
}
cell子类里面实现:
- (void)setDataModel:(KKBaseMessageModel *)model {
self.textLabel.text = @"文本消息";
}
然后我们就可以实现controller里面的协议方法了:
#这里是模拟数据
- (void)getDataArray {
KKTextMessageModel *textModel = [KKTextMessageModel new];
KKImageMessageModel *imageModel = [KKImageMessageModel new];
KKVideoMessageModel *videoModel = [KKVideoMessageModel new];
_dataArray = @[textModel,imageModel,videoModel,imageModel,textModel,videoModel].mutableCopy;
}
#pragma mark UITableView-delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
KKBaseMessageModel *model = self.dataArray[indexPath.row];
KKBaseMessageCell *cell = [self.cellFactory getMessageCellFromModel:model forTableView:tableView];
[cell setDataModel:model];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
KKBaseMessageModel *model = self.dataArray[indexPath.row];
CGSize dataSize = [model dataSizeForMessage];
return dataSize.height-10;
}
这样的代码看起来就简洁多了。