我們常見的設計模式,大致可以分爲三大類:創建型、結構性、行爲型。工廠模式,屬於創建型。
工廠模式到底起的是什麼作用呢?概括來說就是解耦。當某一類對象需要頻繁創建的時候,就會和程序產生比較大的耦合,在對象初始化屬性較多時,工廠模式可以較少這種耦合,這就是他的作用。
一般情況下根據場景不同,工廠模式有幾種不同的形式,簡單工廠、工廠方法和抽象工廠,可以說這三種的關係是層層遞進的。今天我們就說簡單工廠。
首先可以創建RCButton和RCImageView兩個自定義的類用來測試,接下來就就是工廠類的實現
viewFactory.m
@implementation ViewFactory
+(NSObject*)creatViews{
return [[RCButton alloc] init];
}
@end
這樣我們就可以直接調用工廠類的類方法來創建對象了
RCButton *button = [ViewFactory creatViews];
這樣寫完就是一個簡單工廠了,但其實我們並不會這樣寫,因爲一個工廠通常要製造出不同類型的對象,就像一個服裝廠,既可以聲場衣服,又可以生產寫字鞋子,還可以生產帽子等等,其實在工廠類的.m中要這樣寫
+(NSObject*)creatViews:(NSInteger)chose{
NSObject* obj = nil;
switch (chose) {
case 1:
obj = [[RCButton alloc] init];
break;
case 2:
obj = [[RCImageView alloc] init];
break;
default:
obj = [[RCButton02 alloc] init];
break;
}
return obj;
}
這樣我們就可以通過傳入相應的chose來創建我們想要的對象了
RCButton *button = [ViewFactory creatViews:0];
RCImageView *imageView = [ViewFactory creatViews:1];
這樣寫其實還存在一些問題,如果說只有兩三個類型的對象,這種方式就可以滿足了,但如果我們的對象類型很多呢,50個類型要寫50個判斷嗎,有沒有設麼方式可以不去做類型的判斷呢,當然是有的,這個時候,我們一般是把工廠對象設置成單例,然後這樣做
viewFactory.m
static ViewFactory *instance = nil;
+ (id)sharedInstance{
static dispatch_once_t once;
dispatch_once(&once, ^{
instance = [[ViewFactory alloc]init];
});
return instance;
}
- (instancetype)init{
self = [super init];
if (self) {
_dic = [[NSMutableDictionary alloc] init];
[_dic setObject:@"RCButton" forKey:@"1"];
[_dic setObject:@"RCImageView" forKey:@"2"];
[_dic setObject:@"RCImageView02" forKey:@"3"];
}
return self;
}
-(NSObject*)creatViews:(NSInteger)chose{
NSString* name = [NSString stringWithFormat:@"%ld",(long)chose];
return [[NSClassFromString([_dic objectForKey:name]) alloc] init];
}
在工廠類裏面配置好每個key對應的類型,創建對象的時候,直接傳入一個key,就能得到我們想要的對象了,是不是很方便,這樣即使是有100個類型,我們只需要在工廠裏面配置下存儲對象類型的_dic就搞定了。
寫到這裏其實已經很完善了,唯一的不足是對象類型的配置,有更好的方式,那就是通過配置文件去動態的加載對象類型,而不是寫在工廠類裏面。也就是將配置信息放到配置文件中,通過解析配置文件,得到存儲對象類型的_dic
配置文件裏的內容是這樣的
<?xml version="1.0" encoding="UTF-8"?>
<views>
<view key="1" className="RCButton05"/>
<view key="2" className="RCImageView02"/>
<view key="3" className="RCImageView03"/>
<view key="4" className="RCImageView04"/>
<view key="5" className="RCImageView05"/>
<view key="6" className="RCImageView06"/>
<view key="7" className="RCImageView07"/>
<view key="8" className="RCImageView08"/>
</views>
遵循NSXMLParserDelegate之後,解析的過程是這樣的
-(NSMutableDictionary*)parser{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
NSString*path = [[NSBundle mainBundle] pathForResource:@"ViewFactoryConfig" ofType:@"xml"];
NSURL* url = [[NSURL alloc] initFileURLWithPath:path];
NSXMLParser *parser=[[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
[parser parse];
return dic;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(NSDictionary<NSString *, NSString *> *)attributeDict{
_currentElementName = elementName;
if ([elementName isEqualToString:@"view"]) {
NSString* key = [attributeDict objectForKey:@"key"];
NSString* className = [attributeDict objectForKey:@"className"];
[_dic setObject:className forKey:key];
}
}
這樣就拿到了存儲配置信息的_dic,只需在初始化工廠類的時候,執行這個解析的操作,其餘步驟都不用做修改,這樣,一個完整的簡單工廠就實現了,不管是多少個類,我們都不需要去改動的什麼代碼,只需修改配置文件,傳入對應的key,我們就能創建出想要的對象了。
工廠模式中工廠方法的使用http://blog.csdn.net/neveraway1993/article/details/72966001
希望對你有幫助!