一、什么是工厂方法?
正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好地符合了开放封闭原则。工厂方法也叫做虚构造器(Virtual Constructor)。
个人的拙见是:通过工厂方法创建工厂对象,然后在工厂类中定义创建基类的子类对象的方法并通过外部传入的条件判断去创建哪一个子类对象,不过由于OC是运行时语言,所以工厂类虽然提供了创建子类对象的方法,但是在编译时期并不能确定对象类型,编译时期创建的子类对象类型是基类类型,真正的类型在运行时期由子类来确定,也即此时确定为子类类型。
二、工厂方法的实现条件?
(1)存在继承关系
(2)运用了多态的特性
三、工厂方法的优缺点?
优点:极大地优化了代码,如果需要100个子类对象,不用再一直调用alloc方法去创建,而是直接通过其工厂类的一句代码即可实现,提高了对代码的复用性。同时,也可以将大量的操作放到工厂类中去处理,业务类中只负责去调用创建需要的对象即可。
缺点:因为它的实现条件之一必须存在继承关系,所以模式中工厂类集中了所有的创建逻辑,形成一个庞大的全能类,当所有的类不是继承自同一个父类的时候扩展比较困难。
四、创建一个简单的工厂方法如下
工厂类:PersonFactory
// PersonFactory.h // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import <Foundation/Foundation.h>extern NSString *TeacherClassName; extern NSString *StudentClassName;@class Person; @interface PersonFactory : NSObject/*** 定义的一个创建子类对象的接口,通过传入的类名称创建对应的子类对象** @param className 类名称* @param callBlcok 回调,返回创建的子类对象,此时接收子类对象的类型Person类型*/ -(void)createObject:(NSString *)className compelete:(void (^)(Person *object))callBlcok;@end
// PersonFactory // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "PersonFactory.h" #import "Person.h" #import "Teacher.h" #import "Student.h"NSString *TeacherClassName = @"Teacher"; NSString *StudentClassName = @"Student";@implementation PersonFactory-(void)createObject:(NSString *)className compelete:(void (^)(Person *object))callBlcok{if ([className isEqualToString:NSStringFromClass([Teacher class])]) {//创建教师类对象Teacher *teacher = [[Teacher alloc] init];//回调 callBlcok(teacher);//教书 [teacher teachStudent];}if ([className isEqualToString:NSStringFromClass([Student class])]) {//创建学生类的对象Student *student = [[Student alloc] init];//回调 callBlcok(student);//学习 [student learnKnowledge];} }@end
基类:Person(里面提供的方法都被子类重写)
// Person.h // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import <Foundation/Foundation.h>@interface Person : NSObject/*** 打印类名*/ -(void)printClassName;@end
// // Person.m // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "Person.h"@implementation Person-(void)printClassName{}@end
子类教师类:Teacher(重写基类方法的同时,也可以定义属于自己的新的方法)
// Teacher.h // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "Person.h"@interface Teacher : Person/*** 教师的行为*/ -(void)teachStudent; @end
// Teacher.m // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "Teacher.h"@implementation Teacher-(void)printClassName{NSLog(@"%@---%@",NSStringFromClass([self class]),self); }-(void)teachStudent{NSLog(@"teach student"); }@end
子类学生类:Student(重写基类方法的同时,也可以定义属于自己的新的方法)
// Student.h // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "Person.h"@interface Student : Person/*** 学生的行为*/ -(void)learnKnowledge;@end
// Student.m // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import "Student.h"@implementation Student-(void)printClassName{NSLog(@"%@---%@",NSStringFromClass([self class]),self); }-(void)learnKnowledge{NSLog(@"learnKnowledge"); }@end
main.m演示如下:
// main.m // PersonFactory // // Created by 夏远全 on 16/12/23. // Copyright © 2016年 广州市东德网络科技有限公司. All rights reserved. // #import <Foundation/Foundation.h> #import "PersonFactory.h" #import "Person.h" #import "Teacher.h" #import "Student.h"int main(int argc, const char * argv[]) {@autoreleasepool {//创建工厂对象PersonFactory *personFactory = [[PersonFactory alloc] init];//连续创建Person的子类教师类对象for (int i=0; i<5; i++) {[personFactory createObject:TeacherClassName compelete:^(Person *object) {[object printClassName];}];}//连续创建Person的子类学生类对象for (int i=0; i<5; i++) {[personFactory createObject:StudentClassName compelete:^(Person *object) {[object printClassName];}];}}return 0; }
打印结果:
2016-12-23 21:58:51.235 PersonFactory[8896:442793] Teacher---<Teacher: 0x100f01660> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] teach student 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Teacher---<Teacher: 0x103800100> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] teach student 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Teacher---<Teacher: 0x100c005c0> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] teach student 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Teacher---<Teacher: 0x100c00550> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] teach student 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Teacher---<Teacher: 0x100c00180> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] teach student 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Student---<Student: 0x100a00020> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] learnKnowledge 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Student---<Student: 0x100a02880> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] learnKnowledge 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Student---<Student: 0x103900000> 2016-12-23 21:58:51.237 PersonFactory[8896:442793] learnKnowledge 2016-12-23 21:58:51.237 PersonFactory[8896:442793] Student---<Student: 0x103800220> 2016-12-23 21:58:51.238 PersonFactory[8896:442793] learnKnowledge 2016-12-23 21:58:51.238 PersonFactory[8896:442793] Student---<Student: 0x103800230> 2016-12-23 21:58:51.238 PersonFactory[8896:442793] learnKnowledge Program ended with exit code: 0
本人原创,此处是自己对知识的回炉,如果理解有误,请大家不吝赐教,对我进行斧正。