iOS設(shè)計(jì)模式之美-工廠模式
iOS設(shè)計(jì)模式之美-抽象工廠模式
iOS設(shè)計(jì)模式之美-生成器模式
iOS設(shè)計(jì)模式之美-適配器模式
1.何為工廠模式
工廠模式可以簡(jiǎn)單概括為同類型不同型號(hào)的產(chǎn)品有各自對(duì)應(yīng)的工廠進(jìn)行生產(chǎn)渗勘。好比如iPhone
手機(jī)旗下有iPhoneX
及iPhone8
兩種型號(hào)的手機(jī),iPhoneX
有自己iPhoneX
的專屬工廠進(jìn)行生產(chǎn),而iPhone8
有自己iPhone8
的專屬工廠進(jìn)行生產(chǎn)剃根。兩條生產(chǎn)線沒(méi)有交集互不影響杂曲,后期如果新增或廢棄相關(guān)類型的產(chǎn)品也不會(huì)影響到原有的生產(chǎn)線覆履。
工廠模式也稱為虛構(gòu)造器腿时,它適用于:一個(gè)類無(wú)法預(yù)期生成那個(gè)類對(duì)象您炉,想讓其子類來(lái)指定所生成具體對(duì)象原在。
2.何時(shí)使用工廠模式
- 編譯時(shí)無(wú)法確定預(yù)期要?jiǎng)?chuàng)建的對(duì)象類
- 類想讓子類決定運(yùn)行時(shí)創(chuàng)建什么
- 類有若干的輔助子類友扰,而你想將返回那個(gè)子類這一信息局部化
3.工廠模式靜態(tài)類結(jié)構(gòu)圖
由上圖可以知彤叉,工廠模式將都具有拍照功能的同一類產(chǎn)品(iPhoneX
、iPhone8
)抽象為iPhone
村怪,而具體對(duì)應(yīng)的生產(chǎn)工廠則抽象為iPhoneFactory
秽浇。這樣做的好處是即使新增或廢棄其中一類型產(chǎn)品也不會(huì)影響到原有的其他生產(chǎn)線,同時(shí)甚负,不同類型的產(chǎn)品的功能也能得到擴(kuò)展柬焕。如:不同類型的iPhone
手機(jī)的拍照效果具體依賴于其機(jī)型的相關(guān)硬件
4.案例
我們常見(jiàn)的UITableView列
表包含了各種不同的UI
展示的Cell
。我們?cè)谄湎嚓P(guān)的代理方法實(shí)現(xiàn)可能是這樣的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
WCQAStyleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"WCQAStyleTableViewCell"]];
[cell configUI:nil]; //不同樣式的Cell所展示的UI各不相同梭域,由于是Demo樣例斑举,這里并未配置相關(guān)數(shù)據(jù)源
return cell;
}else if (indexPath.row == 1) {
WCQBStyleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"WCQBStyleTableViewCell"]];
[cell configUI:nil];
return cell;
}else if (indexPath.row == 2) {
WCQCStyleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"WCQCStyleTableViewCell"]];
[cell configUI:nil];
return cell;
}
}
隨著需求的迭代,我們后期可能會(huì)增加更多樣式的Cell
病涨,此時(shí)我們就需要變更這部分的代碼富玷。增加與之對(duì)應(yīng)的else if
條件判斷,代碼將變得越來(lái)越長(zhǎng)没宾。同時(shí)凌彬,在更加復(fù)雜的場(chǎng)景下,我們并不能保證調(diào)整原有代碼以后循衰,之前功能不受影響铲敛。我們將投入更多的時(shí)間進(jìn)行原有代碼功能的回歸,這是我們不希望發(fā)生的会钝。
我們發(fā)現(xiàn)上述例子都是通過(guò)不同樣式的Cell
進(jìn)行不同的UI
展示伐蒋,就好比如我們用不同型號(hào)的iPhone
進(jìn)行拍照。我們可以將上述例子調(diào)整為工廠模式迁酸,看看其能為我們帶什么樣的效果先鱼。
1.將各種展示功能相似的Cell
抽象為WCQBaseTableViewCell(繼承于UITableViewCell)
,WCQTableViewCell
提供默認(rèn)展示UI
的方法configUI
2.其他多種的Cell
繼承于WCQBaseTableViewCell
奸鬓,根據(jù)其特定的需求對(duì)configUI
方法進(jìn)覆寫(xiě)焙畔,這里我們以WCQAStyleTableViewCell
為例:
WCQAStyleTableViewCell.h
#import "WCQBaseTableViewCell.h"
@interface WCQAStyleTableViewCell : WCQBaseTableViewCell
@end
WCQAStyleTableViewCell.m
#import "WCQAStyleTableViewCell.h"
@implementation WCQAStyleTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
//UI
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)configUI:(id)model {
self.textLabel.text = NSStringFromClass([self class]);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
3.對(duì)之前UITableView
代理方法進(jìn)行調(diào)整
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WCQBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifiers[indexPath.row]];
[cell configUI:nil];
return cell;
}
這里可能很多同學(xué)會(huì)問(wèn),說(shuō)好的工廠模式怎么只有產(chǎn)品工廠沒(méi)了呢串远?其實(shí)這里[tableView dequeueReusableCellWithIdentifier:self.cellIdentifiers[indexPath.row]]
方法即為一個(gè)工廠宏多。該方法在調(diào)用時(shí)會(huì)執(zhí)行各種樣式Cell
的工廠方法并返回一個(gè)具體產(chǎn)品
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
//UI
}
return self;
}
我們能看到在使用了工廠模式之后,最直觀的感受是代碼量明顯減少了澡罚,也并未依賴具體的實(shí)現(xiàn)類伸但。維護(hù)的代碼越少其BUG
產(chǎn)生的概率也越低。而且留搔,即便是后期有新樣式Cell
的增加更胖,我們也可以在基本不修改原來(lái)客戶端的代碼來(lái)進(jìn)行樣式的增加,我們只需要增加對(duì)應(yīng)Cell
的實(shí)現(xiàn)類以及對(duì)新增樣式Cell
的注冊(cè)即可。對(duì)應(yīng)Cell
的初始化還是UI
展示都封裝進(jìn)了各自的工廠中却妨,互不影響饵逐。
Cell
注冊(cè)代碼示例:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
for (NSInteger index = 0; index < self.cellIdentifiers.count; index++) {
[tableView registerClass:self.cellClasses[index]
forCellReuseIdentifier:self.cellIdentifiers[index]];
}
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
#pragma mark - Getter
- (NSArray *)cellIdentifiers {
if (!_cellIdentifiers) {
_cellIdentifiers = @[@"WCQAStyleTableViewCell",
@"WCQBStyleTableViewCell",
@"WCQCStyleTableViewCell"];
}
return _cellIdentifiers;
}
- (NSArray *)cellClasses {
if (!_cellClasses) {
_cellClasses = @[[WCQAStyleTableViewCell class],
[WCQBStyleTableViewCell class],
[WCQCStyleTableViewCell class]];;
}
return _cellClasses;
}
5.總結(jié)
工廠模式總體在同一類型差異性較小的子類之間以抽象基類作為其返回類型來(lái)適應(yīng)未來(lái)新增產(chǎn)品的動(dòng)態(tài)調(diào)整,由于具有同樣的接口管呵,我們可以在新增產(chǎn)品類型時(shí)盡可能保障原有客戶端代碼邏輯的穩(wěn)定性梳毙。同時(shí),由于各自類型的產(chǎn)品的初始化方案都已隔離進(jìn)各自的工廠方法中捐下,避免了牽一發(fā)而動(dòng)其身的尷尬境地账锹。
以上為本人個(gè)人理解與分享,如有錯(cuò)誤歡迎指出??