iOS設計模式 – (3)簡單工廠模式 – iPhone手機開發技術文章 iPhone軟體開發教學課程

 

 

一。簡述

 


簡單工廠模式(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的判斷即可。怎麼樣很簡單吧。
大概就是這樣, 現在做個總結:

三。總結

優點:
職責單一,實現簡單,且實現瞭客戶端代碼與具體實現的解耦。工廠類是整個模式的關鍵.包含瞭必要的邏輯判斷,根據外界給定的信息,決定究竟應該創建哪個具體類的對象.通過使用工廠類,外界可以從直接創建具體產品對象的尷尬局面擺脫出來,僅僅需要負責“消費”對象就可以瞭。而不必管這些對象究竟如何創建及如何組織的.明確瞭各自的職責和權利,有利於整個軟件體系結構的優化。缺點:
由於工廠類集中瞭所有實例的創建邏輯,違反瞭高內聚責任分配原則,將全部創建邏輯集中到瞭一個工廠類中;它所能創建的類隻能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類瞭。因此它是違背開放封閉原則的。當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不同條件創建不同實例的需求.這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利;註:這些缺點在工廠方法模式中得到瞭一定的克服。
使用場景:工廠類負責創建的對象比較少;客戶隻知道傳入工廠類的參數,對於如何創建對象(邏輯)不關心;由於簡單工廠很容易違反高內聚責任分配原則,因此一般隻在很簡單的情況下應用。

學習的路上, 與君共勉

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *