用处:当需要创建很多新产品的时候可用到。中间采用了反射机制,以返回对象的形式实现。
一、定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
二、何时适⽤工⼚方法
1、编译时⽆法准确预期要创建的对象的类; 2、类想让其子类决定在运行时创建什么; 3、类有若干辅助类为其子类,而你想将返回哪个子类这一信息局部化。
三、优点
1、与直接创建新的具体对象相比,使⽤⼯厂方法创建对象可算是一种最佳做法。 2、⼯厂⽅法模式让客户程序可以要求由⼯厂⽅法创建的对象拥有一组共同的⾏为。 3、往类结构中引⼊新的具体产品并不需要修改客户端代码,因为返回的任何具体对象的接⼝都跟客户端⼀直在⽤的接⼝相同。
四、例⼦
BVShape.h
@interface BVShape : NSObject -(void)draw; @end
BVShape.m
#import "BVShape.h" @implementation BVShape -(void)draw { } @end
BVCircleShpe.h
#import "BVShape.h" @interface BVCircleShpe : BVShape @end
BVCircleShpe.m
#import "BVCircleShpe.h" @implementation BVCircleShpe -(void)draw { NSLog(@"BVCircleShape"); } @end
BVSquareShape.h
#import "BVShape.h" @interface BVSquareShape : BVShape @end
BVSquareShape.m
#import "BVSquareShape.h" @implementation BVSquareShape -(void)draw { NSLog(@"BVSquareShape"); } @end
BVShapeFactory.h
#import "BVShape.h" @interface BVShapeFactory : NSObject +(BVShape *)factoryMethod; @end
BVShapeFactory.m
/* 定义一个类,用来表示生产图形的工厂,定义一个方法,返回一个图形类的实例,这里暂时返回空 这里这个类可以理解为工厂接口 */ #import "BVShapeFactory.h" @implementation BVShapeFactory +(BVShape *)factoryMethod { // ... return nil; } @end
BVCircleShapeFactory.h
#import "BVShapeFactory.h" @interface BVCircleShapeFactory : BVShapeFactory @end
BVCircleShapeFactory.m
/* 定义一个接口类,继承BVShapeFactory类,用来表示生产圆形的工厂,重写父类中的方法,返回一个圆形类的实例 这里这个类可以理解为产品Circle的接口 */ #import "BVCircleShapeFactory.h"
#import "BVCircleShpe.h"
@implementation BVCircleShapeFactory // 重写父类中的factorymethod方法
+(BVShape *)factoryMethod
{
return [[BVCircleShpe alloc] init];
}
@end
BVSquareShapeFactory.h
#import "BVShapeFactory.h" @interface BVSquareShapeFactory : BVShapeFactory @end
BVSquareShapeFactory.m
/* 定义一个类,继承BVShapeFactory类,用来表示生产矩形的工厂,重写父类中的方法,返回一个矩形类的实例 这里这个类可以理解为产品Square的接口 */ #import "BVSquareShapeFactory.h"
#import "BVSquareShape.h"
@implementation BVSquareShapeFactory +(BVShape *)factoryMethod { return [[BVSquareShape alloc] init]; } @end
BVClient.h
@interface BVClient : NSObject -(void)doSomething; @end
BVClient.m
/* 定义一个客户端,用来处理在 工厂实现与工厂接口,产品实现与产品接口 间的关系, 并调用一个方法doSomething()生产产品。 因为在这里也仅仅是在类里面实现了工厂方法的模式,但是还不知道生产的是是吗产品,所以如果想要它在控制台显示出来的话, 就要在AppDelegate.m中实例一个客户端类,调用doSomething()方法,才可以显示出生产出来的产品 */ #import "BVClient.h" #import "BVShape.h" #import "BVCircleShpe.h" #import "BVSquareShape.h" #import "BVShapeFactory.h" #import "BVCircleShapeFactory.h" #import "BVSquareShapeFactory.h" @implementation BVClient -(void)doSomething { //通过工厂方法实例化对应的形状 BVShape * circleShape = [BVCircleShapeFactory factoryMethod]; BVShape * squareShape = [BVSquareShapeFactory factoryMethod]; //调用形状的方法 [circleShape draw]; [squareShape draw]; } @end
AppDelegate.m
#import "AppDelegate.h" #import "BVClient.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //在控制台显示生产出的产品 BVClient * one = [[BVClient alloc] init]; [one doSomething]; [self.window makeKeyAndVisible]; return YES; }
工厂模式:
首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、本文所讲述的工厂方法模式、以及抽象工厂模式。工厂模式是编程中经常用到的一种模式。它的主要优点有:
- 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
- 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
- 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
工厂方法模式:
通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:
- 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
- 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
- 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
- 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。
前文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱,可以算所工厂方法模式的简化版,关于简单工厂模式,在此一笔带过。
适用场景:
不管是简单工厂模式,工厂方法模式还是抽象工厂模式,他们具有类似的特性,所以他们的适用场景也是类似的。
首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。
再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。
转:http://blog.csdn.net/zhengzhb/article/details/7348707