iOS設計模式(代碼分析系列2:簡單工廠模式)

iOS設計模式(代碼分析系列2:簡單工廠模式)

發表於2年前(2014-09-09 21:12)   閱讀(3593) | 評論(0) 8人收藏此文章, 我要收藏
4

4月23日,武漢源創會火熱報名中,期待您的參與>>>>>   

摘要 簡單工廠模式是工廠模式的一種

簡單工廠模式示例代碼下載地址

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)客戶端只知道傳入工廠類的參數,對於如何創建對象的邏輯不必關心時。

六、參考博客

(1)iOS設計模式淺析值簡單工廠模式(SimpleFactory)

(2)設計模式深入學習iOS版(2)簡單工廠模式

(3)計算機簡單工廠模式示例代碼

發佈了2 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章