天天看點

Objective-C常用設計模式(一)--工廠方法模式

工廠方法模式:定義建立對象的接口,讓子類決定執行個體化哪一個類。工廠方法使得一個類的執行個體化延遲到其子類。幾乎所有面向對象語言寫的應用程式都能看到工廠方法。 “專門定義一個類來負責建立其他類的執行個體,被建立的執行個體通常具有共同的父類。”

工廠方法模式使用場景:

  • 編譯時無法準确預期要建立的對象的類;
  • 類想讓其子類決定在運作時建立什麼;
  • 類有若幹輔助類為其子類,而你想将傳回哪個子類這一資訊局部化

結構圖:

Objective-C常用設計模式(一)--工廠方法模式

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方法了,這樣做還是很複雜

那麼這個時候用工廠方法模式就能解決這個難題了

工廠方法模式是為每一個要建立的對象所在的類都相應地建立一個工廠

代碼如下

@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就可以了

但是工廠方法也有它的限制:

1.要建立的類必須擁有同一個父類

2.要建立的類在100個不同的地方所調用的方法必須一樣

例子 

Objective-C常用設計模式(一)--工廠方法模式

從最簡單的簡單工廠模式開始學起,舉一個實作電腦的例子,來完成簡單工廠模式。

一個簡單電腦,用四則運算來考慮的話,加減乘除,那麼初學者會覺得很簡單,用if條件來進行判斷,判斷好了之後就可以完成要求,而稍微有經驗點的 可能會選擇switch case的判斷方式,例如下面的代碼:

Operation運算方法的邏輯

- (void)operationWithnumberA:(double )numberA Withoperator:(char)operator WithnumberB:(double )numberB
{
/**
 *  封裝了一個傳遞值的方法
 *
 *  @param numberA  數字A
 *  @param operator 運算符
 *  @param numberB  數字B
 */
    double result = ;
    
    switch (operator) {
        case 'a':
        result = numberA + numberB;
            break;
            
        case 'b':
            result = numberA - numberB;
            break;
            
        case 'c':
            result = numberA * numberB;
            break;
            
            case 'd':
            if (numberB == ) {
                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 = ;
    
    result = numberA + numberB ;
    
    NSLog(@"%f",result);

    return result;
}




@implementation SubOperation

/**
 *   減法
 */
+ (double)subOperationWithNumberA:(double)numberA WithNumberB:(double)numberB
{
    double result = ;
    
    result = numberA - numberB ;
    
     NSLog(@"%f",result);
    
    return result;
}


@implementation MulOperation

/**
 *   乘法
 */
+ (double)mulOperationWithNumberA:(double)numberA WithNumberB:(double)numberB
{
    double result = ;
    
    result = numberA * numberB ;
    
     NSLog(@"%f",result);
    
    return result;
}

@implementation DivOperation

/**
 *   除法
 */
+ (double)divOperationWithNumberA:(double)numberA WithNumberB:(double)numberB
{
    double result = ;
    
    if (numberB == ) {
        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 = ;
    
    double numberB = ;
    
    
//    NSLog(@"加法請輸入a");
//    NSLog(@"減法請輸入b");
//    NSLog(@"乘法請輸入c");
//    NSLog(@"除法請輸入d");
//    NSLog(@"退出請輸入e");
    
    
    [Operation operationWithnumberA:numberA Withoperator:a WithnumberB:numberB];

}
                

有更好的請給我推薦推薦 謝謝。學習ing

繼續閱讀