簡單工廠模式示例代碼下載地址,
1、簡述
首先需要說明一下,簡單工廠模式不屬於23種GOF設計模式之一。它也稱作靜態工作方法模式,是工廠方法模式的特殊實現(也就是說工廠模式包含簡單工廠模式)。這裏對簡單工廠模式進行介紹,是爲後面的工廠方法和抽象工廠模式做一個引子。
2、定義
“專門定義一個類來負責創建其他類的實例,被創建的實例通常具有共同的父類。”
世界上就是由一個工廠類,根據傳入的參數,動態地決定創建出哪一個產品類的實例。
3、結構圖
簡要分析結構圖:
ConcreteProduct1和ConcreteProduct2兩個產品具有一個共同的父類IProject,簡單工廠類爲SimpleFactory,負責根據傳入的不同參數來決定生產ConcreteProduct1還是ConcreteProduct2產品。
4、代碼示例講解
模擬一個使用計算器的場景:用戶可以輸入兩個數和操作符號,然後得到結果,使用交互如下圖所示,分別進行除運算和減運算,
(1)除運算示例
(2)減運算示例
一個新手,極有可能按照自己的初步思維邏輯,判斷用戶輸入的運算符,然後將兩個數字進行運算,當然還會加上必要的除數不爲0的判斷,那麼點擊運算Button,對應的事件可以如下面這樣編寫,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
- (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]; } } } |
恩,這樣寫肯定能夠實現功能。但是如果進行更多的運算,例如增加開平方、乘方運算,增加100種運算,那麼是不是要增加100個else if判斷語句呢?如果這樣去做每次都要去修改這部分代碼,這樣有悖於可擴展性原則。所以我們需要引入簡單工廠模式,把運算給抽象出來,並且加入運算工廠用於接收用戶的操作。
註釋:這裏我們把運算這個動作給抽象出來,當做一個對象,可能很多人覺得有點迷糊。我們知道,面向對象編程是不同於面向過程編程的,通常將一個事物給抽象成一個類,類具有屬性和方法;那麼我們也可以把一個動作進行抽象,例如此處的運算Operation,它具有兩個屬性(前一個操作數和後一個操作數),它具有的方法就是獲取運算的結果。所以深入理解面向對象編程,還有很多的路要走。
那麼此處我們可以抽象出一個UML圖,如下所示,
與上面的UML結構圖類似,這裏再簡單解釋一下,加、減、乘、除四個運算符都繼承自父類Operation,有兩個屬性和一個操作方法,這些加減乘除的對象並不是直接在ViewController中創建,而是根據輸入操作符,由簡單工廠OperationFactory來創建。
(1)創建一個協議OprationProtocol,由父類Operation來遵從該協議
1
2
3
4
5
6
|
/* * 操作方法協議接口 */ @protocol OperationProtocol <NSObject> -( double )getResult; @end |
(2)定義加減乘除操作的父類Operation
1
2
3
4
5
6
7
8
|
#import OperationProtocol.h /* * 操作方法父類 */ @interface Operation : NSObject<operationprotocol> @property double firstNum; //第一個操作數 @property double secondNum; //第二個操作數 @end |
(3)加減乘除實現類,此處以"加"舉例說明,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//OperationAdd.h文件 #import Operation.h /* * 加法實現類 */ @interface OperationAdd : Operation @end //OperationAdd.m文件 #import "OperationAdd.h" @implementation OperationAdd -( double )getResult { double result = 0; result = self.firstNum+self.secondNum; //"+"是OperationAdd時候使用,"+-*/"分別對應"加減乘除" return result; } @end |
(4)簡單工廠類的代碼,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//OpeartionFactory.h file #import Operation.h #import OperationAdd.h #import OperationSub.h #import OperationMultiply.h #import OperationDivide.h /* * 操作工廠類 */ @interface OperationFactory : NSObject //獲得操作對象 +(Operation*)createOperate:(NSString*)operateStr; @end //OpeartionFactory.m file #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 |
(5)客戶端代碼,在ViewController中使用OperationFactory
1
2
3
4
5
6
7
8
9
|
- (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]]; } |
這樣的話ViewController中的代碼看起來就簡潔明瞭,而且易於擴展。
那麼我們根據ViewController中的代碼,分析一下使用思路,把操作類類比成一個容器,它有輸入端(操作符號、第一個操作數、第二個操作數)和輸出端(運算結果),如下圖所示,
所以上面的代碼將ViewController的TextField中的輸入內容拿過來創建操作對象,並且把操作運算的邏輯放在了Operation及其子類中實現,然後將結果返回給ViewController,這樣減少了ViewController的邏輯代碼。
通過簡單工廠模式的重構,我們就是閒了低耦合度的代碼結構,做到了對外擴展開放,對修改關閉。如果再增加任何的操作方法,只需要繼承操作方法父類,新建一個操作子類,並且在簡單工廠類裏面多添加一個else if的判斷即可。
五、優缺點
優點:簡單工廠模式的優點是客戶端可以直接消費產品,而不必關心具體產品的實現,消除了客戶端直接創建產品對象的責任,實現了對責任的分割。
缺點是工廠類幾種了所有產品的創建邏輯,一旦不能正常工作,整個系統都會受到影響,而且當產品類多結構複雜的時候,把所有創建工作放進一個工廠中來,回事後期程序的擴展較爲困難。
通過優缺點的分析,我們可以再如下場景中使用簡單工廠模式:
(1)工廠類負責創建的對象較少時;
(2)客戶端只知道傳入工廠類的參數,對於如何創建對象的邏輯不必關心時。
六、參考博客