一。簡述
簡單工廠模式(FACTORY),通過面向對象的封裝,繼承和多態來降低程序的耦合度。將一個具體類的實例化交給一個靜態工廠方法來執行。
該模式中的角色包括:
工廠類(Simple Factory): 隻包含瞭創建具體類的靜態方法。抽象產品(Product):定義簡單工廠中要返回的產品。具體產品(ConcreteProduct):具體產品。我們用一張類圖描述這個模式。這裡, 客戶類和工廠類分開。消費者任何時候需要某種產品,隻需向工廠請求即可。消費者無須修改就可以接納新產品。ProductA、ProductB和ProductC繼承自Product虛擬類,Show方法是不同產品的自描述;Factory依賴於ProductA、ProductB和ProductC,Factory根據不同的條件創建不同的Product對象。
二。實例
涉及代碼下載: 比如, 如果我們要實現一個計算器功能, 它包含 + – * / 等基本運算.它的功能大致如下:在不使用設計模式之前, 我們很常規的會寫出下面這樣的代碼:
- (IBAction)getResult:(id)sender { //得到三個文本輸入框的內容 NSString* strFirstNum = self.FirstNumTextField.text; NSString* strSecondNum = self.SecondNumTextField.text; NSString* strOperation = self.OperationTextField.text; //進行運算操作 if ([strOperation isEqualToString:@+]) { NSLog(@+); double result = [strFirstNum doubleValue]+[strSecondNum doubleValue]; self.ResultTextField.text = [NSString stringWithFormat:@%f,result]; } else if([strOperation isEqualToString:@-]) { NSLog(@-); double result = [strFirstNum doubleValue]-[strSecondNum doubleValue]; self.ResultTextField.text = [NSString stringWithFormat:@%f,result]; } else if([strOperation isEqualToString:@*]) { NSLog(@*); double result = [strFirstNum doubleValue]*[strSecondNum doubleValue]; self.ResultTextField.text = [NSString stringWithFormat:@%f,result]; } else if([strOperation isEqualToString:@/]) { NSLog(@/); //判斷除數不能為0 if ([strSecondNum isEqualToString:@0]) { NSLog(@除數不能為0); UIAlertView* tempAlert = [[UIAlertView alloc] initWithTitle:@警告 message:@除數不能為0 delegate:nil cancelButtonTitle:@取消 otherButtonTitles:nil]; [tempAlert show]; } else { double result = [strFirstNum doubleValue]/[strSecondNum doubleValue]; self.ResultTextField.text = [NSString stringWithFormat:@%f,result]; } } }
也就是寫瞭一個方法, 通過傳入的值. 來計算。上面代碼確實可以實現這個功能,但是我們卻沒有考慮到:如果以後需要提供開平方運算,乘方運算擴展時候,改如何做呢?直接加個if else?如果加入瞭100種運算呢?如果這樣去做是不是每次都要去改這部分代碼,這樣有悖我們可擴展性原則。所以我們需要引入簡單工廠模式,把運算給抽象出來,並且加入運算工廠用於接收用戶的操作。
先看下簡單工廠的實現類圖:
根據這一思路. 我們可以寫出如下代碼:
協議接口:
#import /*! * 操作方法協議接口 * * @since V1.0 */ @protocol OperationProtocol -(double)getResult; @end
父類: 實現接口, 說明它有getResult方法
#import #import OperationProtocol.h /*! * 操作方法父類 * * @since V1.0 */ @interface Operation : NSObject @property double firstNum;//第一個操作數 @property double secondNum;//第二個操作數 @end
子類:(以加法為例)
#import Operation.h /*! * 加法實現類 * * @since V1.0 */ @interface OperationAdd : Operation @end
實現:
#import OperationAdd.h @implementation OperationAdd -(double)getResult { double result = 0; result = self.firstNum+self.secondNum; return result; } @end
其他運算類似, 就不重復瞭。
工廠類:
#import #import Operation.h #import OperationAdd.h #import OperationSub.h #import OperationMultiply.h #import OperationDivide.h /*! * 操作工廠類 * * @since V1.0 */ @interface OperationFactory : NSObject //獲得操作對象 +(Operation*)createOperate:(NSString*)operateStr; @end
#import OperationFactory.h @implementation OperationFactory +(Operation*)createOperate:(NSString*)operateStr { Operation* oper = nil; if ([operateStr isEqualToString:@+]) { oper = [[OperationAdd alloc] init]; } else if ([operateStr isEqualToString:@-]) { oper = [[OperationSub alloc] init]; } else if ([operateStr isEqualToString:@*]) { oper = [[OperationMultiply alloc] init]; } else if ([operateStr isEqualToString:@/]) { oper = [[OperationDivide alloc] init]; } return oper; } @end
這裡, 通過工廠類創建瞭運算方法的具體類。
而我們在客戶端部分, 隻要傳入對應的方法即可, 無需知道它的具體實現過程, 如下:
- (IBAction)clickingOperation:(id)sender { NSString* strFirstNum = self.firstNumTextField.text; NSString* strSecondNum = self.secondNumTextField.text; Operation* oper; oper = [OperationFactory createOperate:self.operationTextField.text]; oper.firstNum = [strFirstNum doubleValue]; oper.secondNum = [strSecondNum doubleValue]; self.resultTextField.text = [NSString stringWithFormat:@%f,[oper getResult]]; }
通過簡單工廠模式的重構,這樣我們就實現瞭低耦合度的代碼結構,做到瞭對擴展開放,對修改關閉。如果再增加任何的操作方法,隻需要繼承操作方法父類,新建一個操作子類,並且在工廠方法裡面多加一個if else的判斷即可。怎麼樣很簡單吧。
大概就是這樣, 現在做個總結:
三。總結
優點:
職責單一,實現簡單,且實現瞭客戶端代碼與具體實現的解耦。工廠類是整個模式的關鍵.包含瞭必要的邏輯判斷,根據外界給定的信息,決定究竟應該創建哪個具體類的對象.通過使用工廠類,外界可以從直接創建具體產品對象的尷尬局面擺脫出來,僅僅需要負責“消費”對象就可以瞭。而不必管這些對象究竟如何創建及如何組織的.明確瞭各自的職責和權利,有利於整個軟件體系結構的優化。缺點:
由於工廠類集中瞭所有實例的創建邏輯,違反瞭高內聚責任分配原則,將全部創建邏輯集中到瞭一個工廠類中;它所能創建的類隻能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類瞭。因此它是違背開放封閉原則的。當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不同條件創建不同實例的需求.這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利;註:這些缺點在工廠方法模式中得到瞭一定的克服。
使用場景:工廠類負責創建的對象比較少;客戶隻知道傳入工廠類的參數,對於如何創建對象(邏輯)不關心;由於簡單工廠很容易違反高內聚責任分配原則,因此一般隻在很簡單的情況下應用。
學習的路上, 與君共勉