Factory 方法模式:定義建立對象的介面,讓子類決定執行個體化哪一個類。Factory 方法使得一個類的執行個體化延遲到其子類。幾乎所有物件導向語言寫的應用程式都能看到Factory 方法。 “專門定義一個類來負責建立其他類的執行個體,被建立的執行個體通常具有共同的父類。”
Factory 方法模式使用情境: 編譯時間無法準確預期要建立的對象的類; 類想讓其子類決定在運行時建立什麼; 類有若干輔助類為其子類,而你想將返回哪個子類這一資訊局部化
結構圖:
ConcreteProduct1和ConcreteProduct2兩個產品具有一個共同的父類IProject,簡單工廠類為SimpleFactory,負責根據傳入的不同參數來決定生產ConcreteProduct1還是ConcreteProduct2產品。
代碼例子如下:
Animal 類
@interface Animal :NSObject
@proterty(nonatomic,strong) NSString *name;
-(void)laugh;
@end
Dog類
@interface Dog:Animal
@end
Cat類
@interface Cat:Animal
@end
建立對象的工廠類
.h
@interface AnimalFactory:NSObject
+(Dog *)createDog;
+(Cat *)createCat;
@end
.m
@implementation AnimalFactory
+(Dog *)createDog{
Dog *dog=[[Dog alloc]init];
dog.name=@“baby”;
return dog;
}
+(Cat *) createCat{
Cat *cat=[[Cat alloc]init];
return cat;
}
Main.m檔案
Dog *dog=[AnimalFactory createDog];
Cat *cat=[AnimalFactory createCat];
這是簡單原廠模式
現在建立100個Dog對象,如果這100個對象寫在程式中的不同地方,按上邊的方法是需要把Dog *dog=[AnimalFactory createDog];這一句話寫在程式中很多不同的地方,那麼現在有一個需求,就是如果需要把這些建立的100個Dog對象全部變成Cat對象,那麼按照剛才的那個做法,就需要在這100句代碼中把createDog方法變成createCat方法了,這樣做還是很複雜
那麼這個時候用Factory 方法模式就能解決這個難題了
Factory 方法模式是為每一個要建立的對象所在的類都相應地建立一個工廠
代碼如下
@interface AnimalFactory:NSObject
-(Animal*)createAnimal;
@end;
Dog工廠類
@interface DogFactory:AnimalFactory;
@implementation DogFactory
-(Animal *)createAnimal{
retrurn [[Dog alloc]init];
}
@end
Cat工廠類
@interface CatFactory:AnimalFactory;
@implementation Cat Factory
-(Animal *)createAnimal
retrurn [[Cat alloc]init];
}
@end
Main.m
AnimalFactory *dogFactory=[[DogFactory alloc]init];
Animal *animal1=[dogFactory createAnimal];
[animal1 laugh];
Animal *animal2=[dogFactory createAnimal];
[animal2 laugh];
…….
Animal *animal100=[dogFactory createAnimal];
[animal100 laugh];
這樣話如果要把100個Dog改為Cat的話,只需要吧DogFactory改為CatFactory就可以了
但是Factory 方法也有它的限制:
1.要建立的類必須擁有同一個父類
2.要建立的類在100個不同的地方所調用的方法必須一樣
例子
從最簡單的簡單原廠模式開始學起,舉一個實現計算機的例子,來完成簡單原廠模式。
一個簡單計算機,用四則運算來考慮的話,加減乘除,那麼初學者會覺得很簡單,用if條件來進行判斷,判斷好了之後就可以完成要求,而稍微有經驗點的 可能會選擇switch case的判斷方式,例如下面的代碼:
Operation運算方法的邏輯- (void)operationWithnumberA:(double )numberA Withoperator:(char)operator WithnumberB:(double )numberB{/** * 封裝了一個傳遞值的方法 * * @param numberA 數字A * @param operator 運算子 * @param numberB 數字B */ double result = 0; switch (operator) { case 'a': result = numberA + numberB; break; case 'b': result = numberA - numberB; break; case 'c': result = numberA * numberB; break; case 'd': if (numberB == 0) { NSLog(@"除數不能為0 請重新輸入"); }else{ result = numberA / numberB; } case 'e': NSLog(@"退出"); break; default: break; }
而用戶端方面的代碼 我們可以這麼寫
/** * 四則運算 */- (void)operation{ char a ; double numberA; NSLog(@"請輸入數字A"); scanf("%lf",&numberA); double numberB; NSLog(@"請輸入數字B"); scanf("%lf",&numberB); NSLog(@"加法請輸入a"); NSLog(@"減法請輸入b"); NSLog(@"乘法請輸入c"); NSLog(@"除法請輸入d"); NSLog(@"退出請輸入e"); scanf("%c",&a); [self operationWithnumberA:numberA Withoperator:a WithnumberB:numberB]; }
在我們得到需要的數值之後,調用運算方法做判斷,算出結果。
這樣寫就會比if的判斷清晰,因為我們已經把商務邏輯和介面顯示的部分完全分離了,在任何需要用到的地方,我們就可以直接複製這段代碼,完成運算。
但是假如,我有一天的運算需求不滿足於四則運算,而是希望加上開根號或者平方的運算方法,該怎麼辦。難道我們還要回頭,去switch語句裡再加判斷條件,之後在介面上增加提示麼。
之前的代碼,我們只用到了物件導向的三個特性之一,就是封裝,而解決我上一段話提出的疑問,我們可以用到另外兩個特性,多態和繼承來實現。
為了實現之前的要求,在不改動其他代碼的情況下,能夠增加更多的運算方法,或者修改出問題的運算方法。那麼我們首先先把四則運算,封裝成四個類,即為加法類、減法類、乘法類、除法類。
@implementation AddOperation/** * 加法 */+ (double)addOperationWithNumberA:(double)numberA WithNumberB:(double)numberB{ double result = 0; result = numberA + numberB ; NSLog(@"%f",result); return result;}@implementation SubOperation/** * 減法 */+ (double)subOperationWithNumberA:(double)numberA WithNumberB:(double)numberB{ double result = 0; result = numberA - numberB ; NSLog(@"%f",result); return result;}@implementation MulOperation/** * 乘法 */+ (double)mulOperationWithNumberA:(double)numberA WithNumberB:(double)numberB{ double result = 0; result = numberA * numberB ; NSLog(@"%f",result); return result;}@implementation DivOperation/** * 除法 */+ (double)divOperationWithNumberA:(double)numberA WithNumberB:(double)numberB{ double result = 0; if (numberB == 0) { NSLog(@"除數不能為0 請重新輸入"); }else{ result = numberA / numberB; } NSLog(@"%f",result); return result;}
這樣我們就已經把四則運算,封裝成了四個類。因為偷懶,我並沒有設計介面模型,只是把結果輸出來,所以每段輸出結果的NSLog請不要介意。
接下來,我們在簡單工廠的Operation類中,把調用這四個類的運算方法實現。
/** * 封裝了一個運算方法 * * @param numberA 數字A * @param operator 運算子 * @param numberB 數字B */+ (void)operationWithnumberA:(double )numberA Withoperator:(char)operator WithnumberB:(double )numberB{ switch (operator) { case 'a': [AddOperation addOperationWithNumberA:numberA WithNumberB:numberB]; break; case 'b': [SubOperation subOperationWithNumberA:numberA WithNumberB:numberB]; break; case 'c': [MulOperation mulOperationWithNumberA:numberA WithNumberB:numberB]; break; case 'd': [DivOperation divOperationWithNumberA:numberA WithNumberB:numberB]; break; case 'e': NSLog(@"退出"); break; default: break; } }
以上就是在簡單工廠的類中,調用四個運算方法的類,來實現運算,並且成功解耦合,有利於以後的維護和擴充。用戶端方面的代碼也就非常簡單。
/** * 四則運算 */- (void)operation{ char a = 'a'; double numberA = 10; double numberB = 20; // NSLog(@"加法請輸入a");// NSLog(@"減法請輸入b");// NSLog(@"乘法請輸入c");// NSLog(@"除法請輸入d");// NSLog(@"退出請輸入e"); [Operation operationWithnumberA:numberA Withoperator:a WithnumberB:numberB];}
有更好的請給我推薦推薦 謝謝。學習ing