歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> iOS開發-簡單工廠模式與OC反射機制

iOS開發-簡單工廠模式與OC反射機制

日期:2017/3/1 9:26:28   编辑:Linux編程

在iOS開發中,簡單工廠模式使用得並不多。但是我認為這是OC反射機制很好的一個例子,所以本文將以計算器為例,講解簡單工廠模式和OC的反射機制。

環境信息:

Mac OS X 10.9

Xcode 5.1.1

正文:

簡單工廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該創建哪一個產品類(這些產品類繼承自一個父類或接口)的實例。該模式中包含的角色及其職責:工廠角色、抽象產品角色、具體產品角色

——百度百科 簡單工廠模式

上面這句話可能不怎麼好理解,我在網上找到了一個例子,可能例子本身不能完全解釋這個設計模式的優點,但是它將角色和職責介紹得很清楚:


一個男生想要請女生吃飯,但是這個男生不會做飯。那麼干脆就到麥當勞去,讓女生自己點喜歡吃的東西就可以了。

在這個例子中,麥當勞就是工廠角色,麥當勞中的產品就是抽象產品角色,薯條、漢堡就是具體產品角色。

按照這種思維模式,我們可以畫出計算器的UML類圖:

簡單工廠模式類圖

根據類圖我們搭框架並進行編碼:

計算器頭文件:Calculate.h

#import <Foundation/Foundation.h>
#import "Operation.h"

@interface Calculate : NSObject

// 一個計算的類方法
+ (float)calculate:(float)number1 number2:(float)number2 operators:(NSString *)operators;

@end

計算器方法實現:Calculate.m

#import "Calculate.h"

@implementation Calculate

+ (float)calculate:(float)number1 number2:(float)number2 operators:(NSString *)operators {
// 使用OC反射獲得一個與字符串同名的類(將在本文後面進行詳細講解)
Class class = NSClassFromString(operators);
// 實例化這個類,並傳入計算器的兩個操作數
Operation *operation = [[class alloc] initWithNumebr1:number1 number2:number2];
// 調用運算方法,並返回結果
return [operation operate];
}

@end

抽象運算類Operation.h

#import <Foundation/Foundation.h>

@interface Operation : NSObject

@property (nonatomic) float number1;
@property (nonatomic) float number2;

- (float)operate; // 運算方法:所有具體運算類都將重寫該方法,用於實現子類自己的邏輯
- (Operation *)initWithNumebr1:(float)number1 number2:(float)number2;

@end

抽象運算類方法實現Operation.m (實現initWithNumebr1:number2:方法即可)

加法運算類Addition.h

#import "Operation.h"

// 繼承抽象運算類Operation
@interface Addition : Operation
@end

加法運算類方法實現Addition.m (重寫Operation類中的operate方法,實現加法邏輯即可)

客戶端main

#import <Foundation/Foundation.h>
#import "Calculate.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
// 將操作數1,操作數2,和操作符輸入到計算器中
// 操作符即加法類類名
NSLog(@"%.2f", [Calculate calculate:1 number2:2 operators:@"Addition"]);
}
return 0;
}

通過以上代碼,我們就成功實現了一個簡單工廠模式的計算器。下面將講解下OC的反射機制:


對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

——百度百科 java反射

上面這句話是對java反射的介紹,我們也可以把它看做是OC反射的介紹。

例如上面的計算器程序,我們使用的是NSClassFromString方法來使用字符串獲得類。對於如何使用反射,獲得類中的方法、調用對象的方法、獲取對象屬於某個類等操作,我寫在了下面這篇文章中:

NSObject方法介紹

反射的好處還在於團隊合作時,如果對方負責的類並沒有完全實現,如果這時你引入肯定會報錯,那麼就可以用到反射。

--------------------------------------分割線 --------------------------------------

NSObject方法介紹

NSObject是OC中的基類,所有類都繼承於此,這裡面也給我們提供了很多與“類”和“方法”相關的方法,本文將講解幾個非常實用的方法。

環境信息:

Mac OS X 10.9

xcode 5.1.1

正文:

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject
@end

Student.h

#import "Person.h"

// 繼承Person類
@interface Student : Person

- (void)test1;
- (void)test2:(NSString *)string;

@end

MyProtocol.h

#import <Foundation/Foundation.h>

@protocol MyProtocol
@end

1. 判斷student是否是Person類的對象

// - (BOOL)isMemberOfClass:(Class)aClass;
[student isMemberOfClass:[Person class]];

2. 判斷student是否是Person類或子類的對象

// - (BOOL)isKindOfClass:(Class)aClass;
[student isKindOfClass:[Person class]];

3. 判斷student是否遵循MyProtocol協議(也可以用類調用,判斷該類是否遵循)

// - (BOOL)conformsToProtocol:(Protocol *)aProtocol;
[student conformsToProtocol:@protocol(MyProtocol)];

// 或者使用類方法
// + (BOOL)conformsToProtocol:(Protocol *)protocol;
[Student conformsToProtocol:@protocol(MyProtocol)];

4. 判斷student的test1方法是否響應(即:是否聲明並實現了test1方法)

// - (BOOL)respondsToSelector:(SEL)aSelector;
[student respondsToSelector:@selector(test1)];

5. 間接調用student的test1方法(test1無參數)

// - (id)performSelector:(SEL)aSelector;
[student performSelector:@selector(test1)];

6. 間接調用student的test2方法(test2有一個參數)

// - (id)performSelector:(SEL)aSelector withObject:(id)object;
[student performSelector:@selector(test2:) withObject:@"123"];

// 最多帶兩個參數
//- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

7. 延遲2s調用student的test1方法

(在命令行沒有延遲效果,因為命令行執行完後就退出main函數了 ,在IOS部分main函數一直在執行,所以可以看到延遲效果)

// - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
// delay單位為(秒)
[student performSelector:@selector(test2:) withObject:@"123" afterDelay:2];

Copyright © Linux教程網 All Rights Reserved