工厂方法模式是抽象工作模式的组成部分。
工厂方法也成为虚构造器,他适用于这种情况:一个类无法预期需要生成那个类的对象,想让其子类来指定所生成的对象。
工厂方法模式:定义创建对象的接口,让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到其子类。
何时使用工厂方法:
1、编译时无法准确预期要创建的对象的类
2、类想让其子类决定在运行时创建什么
3、类有若干辅助类为其子类,而你想将反悔哪个子类这一信息局部化
类工厂方法是创建对象的安全方法:
工厂方法模式让客户端可以要求由工厂方法创建的对象拥有一组共同的行为。所以往类层次结构中引入新的具体产品并不需要修改客户端代码,因为返回的任何具体对象的接口都跟客户端一直在用的以前的接口相同。
下面我们先创建产品类:
People类有两个属性和一个初始化方法,同时,这个类也是其他产品类的父类。
// People.h #import <Foundation/Foundation.h> @interface People : NSObject @property (nonatomic, copy) NSString * name; @property (nonatomic, copy) NSString * age; - (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age; @end // People.m #import "People.h" @implementation People - (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age { self = [super init]; if(self){ self.name = name; self.age = age; } return self; } - (NSString *)description { return [NSString stringWithFormat:@"我的名字是:%@, 我的年龄是%@", self.name, self.age]; } @end
Student类继承People类,添加了一个新的属性StudentDescription,重写了初始化方法- (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age
1 // Student.h 2 3 #import <Foundation/Foundation.h> 4 #import "People.h" 5 6 @interface Student : People 7 8 @property (nonatomic, copy) NSString * StudentDescription; 9 10 @end 11 12 13 // Student.m 14 15 #import "Student.h" 16 17 @implementation Student 18 19 - (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age 20 { 21 self = [super initPeopleWithName:name andAge:age]; 22 if(self){ 23 _StudentDescription = @"我是一个学生"; 24 } 25 26 return self; 27 } 28 29 - (NSString *)description 30 { 31 return [NSString stringWithFormat:@"%@,我的名字是:%@, 我的年龄是:%@", self.StudentDescription, self.name, self.age]; 32 } 33 @end
Programmer类继承自People类,添加了两个属性ProgrammerDescription和workType,并重写了初始化方法: - (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age,在初始化方法中,初始化方法中给两个属性赋值
1 // Programmer.h 2 3 #import <Foundation/Foundation.h> 4 #import "People.h" 5 6 @interface Programmer : People 7 8 @property (nonatomic, copy) NSString * ProgrammerDescription; 9 @property (nonatomic, copy) NSString * workType; 10 11 @end 12 13 14 // Programmer.m 15 16 #import "Programmer.h" 17 18 @implementation Programmer 19 20 - (id)initPeopleWithName:(NSString *)name andAge:(NSString *)age 21 { 22 self = [super initPeopleWithName:name andAge:age]; 23 24 if(self){ 25 _ProgrammerDescription = @"我已经工作了"; 26 _workType = @"我的工作是程序员"; 27 } 28 29 return self; 30 } 31 32 - (NSString *)description 33 { 34 return [NSString stringWithFormat:@"%@, %@, 我的名字是:%@, 我的年龄是%@", self.ProgrammerDescription, self.workType, self.name, self.age]; 35 } 36 37 @end
下面我们来创建生成器方法:
Creator类为People的生成器对象,同时他也是其他生成器的父类。
1 // Creator.h 2 3 #import <Foundation/Foundation.h> 4 #import "People.h" 5 6 @interface Creator : NSObject 7 8 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age; 9 10 @end 11 12 13 14 // Creator.m 15 16 #import "Creator.h" 17 18 @implementation Creator 19 20 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age 21 { 22 return [[People alloc] initPeopleWithName:name andAge:age]; 23 } 24 25 @end
我们可以为每款产品创建一个生成器:所以我们生成了CreateStudent和CreateProgrammer两个生成器分别用来生成Student和Programmer对象
CreateStudent类继承自Creator
1 // CreateStudent.h 2 3 #import <Foundation/Foundation.h> 4 #import "Creator.h" 5 6 @interface CreateStudent : Creator 7 8 9 @end 10 11 12 // CreateStudent.m 13 14 #import "CreateStudent.h" 15 #import "Student.h" 16 17 @implementation CreateStudent 18 19 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age 20 { 21 return [[Student alloc] initPeopleWithName:name andAge:age]; 22 } 23 24 @end
CreateProgrammer同样也继承自Creator
1 // CreateProgrammer.h 2 3 #import <Foundation/Foundation.h> 4 #import "Creator.h" 5 6 @interface CreateProgrammer : Creator 7 8 @end 9 10 11 // CreateProgrammer.m 12 13 #import "CreateProgrammer.h" 14 #import "Programmer.h" 15 16 @implementation CreateProgrammer 17 18 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age 19 { 20 return [[Programmer alloc] initPeopleWithName:name andAge:age]; 21 } 22 23 @end
这种情况的调用:
1 People * people = [[Creator alloc] createPeopleWithName:@"坏人" andAge:@"25"]; 2 NSLog(@"%@", people); 3 4 People * people2 = [[CreateStudent alloc] createPeopleWithName:@"坏学生" andAge:@"18"]; 5 NSLog(@"%@", people2); 6 7 People * people3 = [[CreateProgrammer alloc] createPeopleWithName:@"坏员工" andAge:@"30"]; 8 NSLog(@"%@", people3);
生成结果:
上面的方法,每次扩展产品的时候,都需要创建一个生成器子类,这样做起来有些麻烦。我们也可以为每一类产品的子类创建一个公用的生成器。
首先生成Creator类:
1 // Creator.h 2 3 #import <Foundation/Foundation.h> 4 #import "People.h" 5 6 @interface Creator : NSObject 7 8 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age withType:(NSString *)strType; 9 10 @end 11 12 13 14 // Creator.m 15 16 #import "Creator.h" 17 18 @implementation Creator 19 20 21 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age withType:(NSString *)strType 22 { 23 return [[People alloc] initPeopleWithName:name andAge:age]; 24 } 25 26 @end
然后生成子类的生成器:
1 // CreatePeople.h 2 3 #import <Foundation/Foundation.h> 4 #import "Creator.h" 5 6 @interface CreatePeople : Creator 7 8 @end 9 10 11 // CreatePeople.m 12 13 #import "CreatePeople.h" 14 #import "Student.h" 15 #import "Programmer.h" 16 17 @implementation CreatePeople 18 19 - (People *)createPeopleWithName:(NSString *)name andAge:(NSString *)age withType:(NSString *)strType 20 { 21 if([strType isEqualToString:@"stu"]){ 22 return [[Student alloc] initPeopleWithName:name andAge:age]; 23 }else if([strType isEqualToString:@"pro"]){ 24 return [[Programmer alloc] initPeopleWithName:name andAge:age]; 25 } 26 27 return nil; 28 } 29 30 @end
调用代码:
1 People * people = [[CreatePeople alloc] createPeopleWithName:@"坏学生" andAge:@"25" withType:@"stu"]; 2 NSLog(@"%@", people); 3 People * people2 = [[CreatePeople alloc] createPeopleWithName:@"坏员工" andAge:@"30" withType:@"pro"]; 4 NSLog(@"%@", people2);
输出结果:
工厂方法的变体:
我们可以将对象分为两个步骤创建:1、分配空间,2、初始化。例如:
1 NSString * str = [[NSString alloc] initWithFormat:@"%@", @"好人"];
还有一些比较便利的方法返回类的实例(类方法,以+开头的方法),例如:
1 NSString * str = [NSString stringWithFormat:@"%@", @"好人"];
这些比较便利创建对象的方法,是在类级别打包提供了类似工厂方法效果,它们称作类工厂方法。
工厂方法是面向对象软件设计中应用非常普遍的设计模式,工厂方法从代码中消除了对应用程序特有类的耦合。