【iOS類簇】工廠設(shè)計(jì)模式(Class Cluster)

摘要軟件的設(shè)計(jì)模式如同高樓的設(shè)計(jì)藍(lán)圖,優(yōu)秀巧妙應(yīng)用設(shè)計(jì)模式可以使編碼者更加輕松,軟件的架構(gòu)也會(huì)更加合理,這篇博客主要探討工廠設(shè)計(jì)模式,iOS中的類簇,就是工廠模式的一種實(shí)現(xiàn)。

工廠設(shè)計(jì)模式的探討——iOS類簇的應(yīng)用分析

一、何為設(shè)計(jì)模式

什么是設(shè)計(jì)模式,先來(lái)看段度娘的話:
設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無(wú)疑問(wèn),設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的;設(shè)計(jì)模式使代碼編制真正工程化;設(shè)計(jì)模式是軟件工程的基石脈絡(luò),如同大廈的結(jié)構(gòu)一樣。

其實(shí)我們不需要這么專業(yè),在我的理解,設(shè)計(jì)模式就是一種規(guī)范化的編程習(xí)慣,養(yǎng)成了這樣的思想與習(xí)慣,對(duì)我們的代碼,總是有好處了。

二、工廠設(shè)計(jì)模式

首先,工廠設(shè)計(jì)模式是創(chuàng)建對(duì)象的一種設(shè)計(jì)模式,一個(gè)嚴(yán)格意義上的工廠設(shè)計(jì)模式應(yīng)該是一個(gè)純虛的構(gòu)造方法。由子類進(jìn)行具體對(duì)象的創(chuàng)建,我們可以這樣理解:現(xiàn)在有一個(gè)琿少牌制造工廠,這個(gè)工廠可以制造多種交通工具,我大膽一些,假設(shè)它可以制造飛機(jī),輪船。小汽車,公交車,出租出和自行車,那么,這些不同的車種雖然功能和大類別統(tǒng)一,但是他們的個(gè)體差異也是天地之別,就比如我飛機(jī)一小時(shí)可以飛5000公里,自行車拼死了勁也不一定能騎20公里。所以,如果琿少這個(gè)大工廠要生產(chǎn)他們,也不可能把他們放在一起生產(chǎn)。一個(gè)比較明智的決定是,開(kāi)立分廠,比如琿少飛機(jī)工廠專門生產(chǎn)飛機(jī),琿少自行車工廠專門生產(chǎn)自行車。
好了,如果將我們這種人類世界的思維運(yùn)用于程序世界,那么我們可以通過(guò)工廠的這種思維方式來(lái)將一些大類抽象為工廠,通過(guò)定義接口或者說(shuō)是定義虛函數(shù)來(lái)規(guī)范這個(gè)大工廠的生產(chǎn)規(guī)模和流程,由其子類來(lái)具體實(shí)現(xiàn)這些方法,也就是由一個(gè)個(gè)小的分廠來(lái)明確的生產(chǎn)我們需要的東西。這就是工廠設(shè)計(jì)模式的基本思路。

三、工廠的設(shè)計(jì)模式有什么用

許多開(kāi)發(fā)者或許并不在意設(shè)計(jì)模式這個(gè)東西,我們可能會(huì)想,我實(shí)現(xiàn)我的功能就可以了,你管我怎么設(shè)計(jì)呢。在這篇博客的開(kāi)頭就說(shuō)到,在我理解中,設(shè)計(jì)模式就是一種編程習(xí)慣和規(guī)范,更是一種眾多開(kāi)發(fā)者摸索出來(lái)的經(jīng)驗(yàn),這就像農(nóng)業(yè)上的套種間種和你隨便種,哪一種效率高,收成好,不言而喻。那么在軟件設(shè)計(jì)中,工廠模式的應(yīng)用在哪呢?
我們先來(lái)體驗(yàn)一下在iOS開(kāi)發(fā)中,一些使用工廠設(shè)計(jì)模式的系統(tǒng)類為我們帶來(lái)的便捷之處:
1、認(rèn)識(shí)一個(gè)名詞 類簇
在iOS的Foundation框架中,類簇是一種常用的設(shè)計(jì)模式,他將一些相近的,私有的,具體的子類組合在一個(gè)實(shí)體的抽象類下面,我稱這個(gè)抽象類為實(shí)體的,是因?yàn)楹臀覀兘换サ慕涌诔休d者,就是這個(gè)抽象大類。我們平時(shí)常用的三大類,NSString,NSArray,NSDictionary都是類簇,我們通過(guò)他們創(chuàng)建的對(duì)象都是其子類對(duì)象的實(shí)例化,并不是他本身的實(shí)例化,我們還通過(guò)上面的例子來(lái)理解,我買了一輛琿少小汽車,這兩汽車的生產(chǎn)實(shí)際是在琿少汽車工廠生產(chǎn)的,但是我個(gè)人會(huì)依然認(rèn)為,這是琿少工廠出產(chǎn)的汽車。我們可以通過(guò)打印類名來(lái)驗(yàn)證:
NSString * str = [[NSString alloc]initWithCString:"2" encoding:0]; NSLog(@"%@",[str class]);

結(jié)果如下:



可以看到,真實(shí)的對(duì)象是NSString的子類__NSCFString進(jìn)行實(shí)例化的。
2.這樣設(shè)計(jì)的優(yōu)勢(shì)在哪
如果你通過(guò)NSString的事例還是無(wú)法體會(huì)到類簇,也就是工廠設(shè)計(jì)模式的優(yōu)勢(shì),那么下面這個(gè)例子你一定經(jīng)常遇到:NSNumber。我們?cè)趧?chuàng)建數(shù)字對(duì)象的時(shí)候,通常會(huì)這樣考慮,如果是int值,我需要一個(gè)IntNumber的類,float值,我需要一個(gè)FloatNumber類,如果foundation框架真這么設(shè)計(jì)的話,那么你現(xiàn)在就痛苦了,你不僅要記住好多這樣相似的類,調(diào)用方法時(shí)也要相應(yīng)的對(duì)象調(diào)其內(nèi)的方法,這使開(kāi)發(fā)者的開(kāi)發(fā)變得更加繁瑣,并且對(duì)于開(kāi)發(fā)者來(lái)說(shuō),我并不需要知道具體我創(chuàng)建了什么類,我只是想讓他完成既定的方法。說(shuō)的更通俗一點(diǎn),還是上面的制造工廠,使用者并不在乎具體這個(gè)交通工具是哪個(gè)地方生產(chǎn)出來(lái)的,只要它價(jià)錢和速度都是使用者預(yù)期的結(jié)果就好了。
3.工廠設(shè)計(jì)模式的應(yīng)用
通過(guò)上面的分析,我們大致可以總結(jié)出工廠這種設(shè)計(jì)模式的應(yīng)用場(chǎng)景:
(1)當(dāng)一個(gè)類并不知道要?jiǎng)?chuàng)建的具體對(duì)象是什么,交由子類處理
(2)當(dāng)一些類有相似的行為和結(jié)構(gòu),只是具體實(shí)現(xiàn)不同時(shí),可以抽象出工廠
(3)使用者并不在乎具體類型,只在乎接口約定的行為,并且這種行為有個(gè)體差異

四、在iOS中模擬一個(gè)工廠

同樣是上面的例子,我們來(lái)用代碼模擬一下:
首先,我們創(chuàng)建一個(gè)抽象的工程類,在其中創(chuàng)建一些私有的子類:

#import <Foundation/Foundation.h>//交通工具的枚舉
typedef enum {car,boat,airport,bycicle,bus,taxi}ToolsName;
  //代理
@protocol TransPortationDelegate <NSObject>
-(void)toHome:(Class)class;
@end
//抽象工廠類
@interface TramsPortationFactory : NSObject
+(TramsPortationFactory*)buyTool:(ToolsName)tool;//共有的方法接口
-(int)shouldPayMoney;
-(void)run;
@property(nonatomic,strong)id<TransPortationDelegate>delegate;
@end

//具體實(shí)現(xiàn)的子類(新建文件)
@interface CarFactory : TramsPortationFactory
@end

@interface BoatFactory : TramsPortationFactory
@end

@interface AirportFactory : TramsPortationFactory
@end

@interface BycicleFactory : TramsPortationFactory
@end

@interface TaxiFactory : TramsPortationFactory
@end

@interface BusFactory : TramsPortationFactory
@end

實(shí)現(xiàn)文件如下:

#import "TramsPortationFactory.h"
#impor "CarFactory.h"
//引入所有私有子類的頭文件
@implementation TramsPortationFactory//實(shí)現(xiàn)的創(chuàng)建方法
+(TramsPortationFactory*)buyTool:(ToolsName)tool{ 
   switch (tool) {       
       case car:            
          return [[CarFactory alloc]init];
          break;
       case airport: 
           return [[AirportFactory alloc]init];
           break; 
       case bycicle: 
           return [[BycicleFactory alloc]init]; 
           break;
       case boat:  
           return [[BoatFactory alloc]init];  
            break; 
       case taxi:
            return [[TaxiFactory alloc]init];  
            break; 
       case bus: 
             return [[BusFactory alloc]init];
            break; 
       default: 
             break;    }
}
-(int)shouldPayMoney{ 
   return 0;
}
-(void)run{ 
   [self.delegate toHome:[self class]];
}
@end

//各自類實(shí)現(xiàn)具體的行為
@implementation CarFactory
-(int)shouldPayMoney{   
 return 50;
}
-(void)run{
    [super run];
    NSLog(@"car to home");
}
@end

@implementation AirportFactory
-(int)shouldPayMoney{
    return 1000;
}
-(void)run{
    [super run];
    NSLog(@"fly to home");
}
@end

@implementation BoatFactory
-(int)shouldPayMoney{
    return 300;
}
-(void)run{
    [super run];
    NSLog(@"boat to home");
}
@end

@implementation BusFactory
-(int)shouldPayMoney{
    return 10;
}
-(void)run{
    [super run];
    NSLog(@"bus to home");
}
@end

@implementation BycicleFactory
-(int)shouldPayMoney{
    return 0;
}
-(void)run{ 
   [super run];
    NSLog(@"run to home");
}
@end

@implementation TaxiFactory
-(int)shouldPayMoney{
    return 100;
}
-(void)run{
    [super run];
    NSLog(@"go to home");
}
@end

這樣,我們的一個(gè)生產(chǎn)工廠就完成了,在外面,我們只需要知道一個(gè)類,我們的抽象父類,就可以實(shí)現(xiàn)個(gè)子類的行為,示例如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    TramsPortationFactory * tool = [TramsPortationFactory buyTool:car]; 
   tool.delegate=self;
    [tool run];//成員關(guān)系從屬于CarFactory類,所以調(diào)用CarFactory類中的run方法
    NSLog(@"花了:%d錢",[tool shouldPayMoney]);
    TramsPortationFactory * tool2 = [TramsPortationFactory buyTool:airport]; 
   tool2.delegate=self; 
   [tool2 run]; 
   NSLog(@"花了:%d錢",[tool2 shouldPayMoney]);
 }
-(void)toHome:(Class)class{
    NSLog(@"%@",NSStringFromClass(class));
}


可以看到,對(duì)于開(kāi)發(fā)者,我們并不知曉CarFactory類的存在,我們只需要通過(guò)TramsPortationFactory類,就能夠操作各種交通工具,達(dá)到我們的需求。

綜上所述:

工廠設(shè)計(jì)模式,即使用類簇的概念,創(chuàng)建一個(gè)抽象的公共類,創(chuàng)建多個(gè)繼承自該抽象公共類的子類,由子類實(shí)現(xiàn)不同的功能,然后將子類引入到父類,即抽象公共類的.m實(shí)現(xiàn)文件中,通過(guò)父類調(diào)用特定方法實(shí)例化子類,進(jìn)一步調(diào)用子類的實(shí)現(xiàn)方法,可以很好地隱藏子類的接口及實(shí)現(xiàn)方式。注意,子類接口和實(shí)現(xiàn)不能直接寫入到父類文件中,會(huì)暴漏子類接口給外界,所以子類文件需要重新創(chuàng)建,并引入到父類.m中隱藏或打包成靜態(tài)庫(kù)由抽象公共類統(tǒng)一調(diào)用管理。

文章出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 簡(jiǎn)單工廠模式 工廠模式我的理解是:他就是為了創(chuàng)建對(duì)象的 創(chuàng)建對(duì)象的時(shí)候,我們一般是alloc一個(gè)對(duì)象,如果需要?jiǎng)?chuàng)建...
    GitHubPorter閱讀 8,206評(píng)論 6 16
  • 抽象工廠模式 介紹 工廠方法模式通過(guò)引入工廠等級(jí)結(jié)構(gòu),解決了簡(jiǎn)單工廠模式中工廠類職責(zé)太重的問(wèn)題,但由于工廠方法模式...
    666真666閱讀 1,309評(píng)論 0 7
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,073評(píng)論 1 15
  • 一、設(shè)計(jì)模式的分類 總體來(lái)說(shuō)設(shè)計(jì)模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    RamboLI閱讀 825評(píng)論 0 1
  • 1.求而不得本就是人生常態(tài) 我有個(gè)朋友小宋姑娘一直夢(mèng)想成為一名老師,并且一直為之努力。 上個(gè)月,到了查詢成績(jī)的那一...
    蘇小鹿lu閱讀 3,011評(píng)論 4 9

友情鏈接更多精彩內(nèi)容