前言
几乎在每个面向对象语言写的应用程序里都能看到工厂方法。对象工厂与生成有形产品的真实工厂类似,例如:制鞋厂生产鞋,手机工厂生产手机。比方说,你让工厂给你生产些产品,发送一个 “生产产品” 的消息,工厂按照相同的 “生产产品的协议” ,启动其生产线,过程结束后,每个厂家都返回所生产的特定类型的产品。我们把 ”生产“ 这个有魔力的词称作工厂方法,因为它是命令生产者得到想要的产品的方法。
什么是工厂方法模式
工厂方法,也成为虚构造器。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂方法模式使其创建过程延迟到子类进行。其从代码中消除了对特有类的耦合,只需处理抽象接口,同一代码得到复用。
工厂方法模式的类图.png 抽象的 Product
定义了工厂方法创建的对象的接口,ConcreteProduct
实现了 Product
的接口。Factory
定义了返回 Product
对象的工厂方法,ConcreteFactory
重载了工厂方法,返回 ConcreteProduct
实例。
什么时候使用工厂方法
- 编译时无法准确预期要创建的对象的类
- 类想让其子类决定在运行时创建什么
- 类有若干辅助类为其子类,将返回哪个子类这一信息局部化。
工厂方法使用场景举例
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问:当不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
工厂方法的优缺点
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以,无需调用的代码
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点
- 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
实现
普通工厂方法的实现
-
定义一个抽象
Shape
协议。@protocol Shape <NSObject> @property (nonatomic, copy) NSString *Id; @property (nonatomic, copy) NSString *type; - (void)draw; @end
-
定义三个 Shape 的子类分别为
Rectangle
、Circle
和Square
@interface Rectangle : NSObject<Shape> @end @implementation Rectangle @synthesize Id; @synthesize type; - (instancetype)init { self = [super init]; if (self) { self.type = @"Rectangle"; } return self; } - (void)draw{ NSLog(@"call Rectangle draw() method."); } @end @interface Circle : NSObject<Shape> @end @implementation Circle @synthesize Id; @synthesize type; - (instancetype)init { self = [super init]; if (self) { self.type = @"Circle"; } return self; } - (void)draw{ NSLog(@"call Circle draw() method."); } @end @interface Square : NSObject<Shape> @end @implementation Square @synthesize Id; @synthesize type; - (instancetype)init { self = [super init]; if (self) { self.type = @"Square"; } return self; } - (void)draw{ NSLog(@"call Square draw() method."); } @end
-
定义一个
ShapeFactory
抽象@protocol
,负责创建Shape
,以及遵守协调的CircleFactory
、RectangleFactory
和SquareFactory
负责创建Circle
、Rectangle
和Square
。@protocol ShapeFactory - (id<Shape>)shapeWithId:(NSString *)Id; @end @interface CircleFactory : NSObject <ShapeFactory> @end @implementation CircleFactory - (Circle *)shapeWithId:(NSString *)Id{ Circle *circle = [Circle new]; circle.Id = Id; return circle; } @end @interface RectangleFactory : NSObject <ShapeFactory> @end @implementation RectangleFactory - (id<Shape>)shapeWithId:(NSString *)Id{ Rectangle *rectangle = [Rectangle new]; rectangle.Id = Id; return rectangle; } @end @interface SquareFactory : NSObject <ShapeFactory> @end @implementation SquareFactory - (id<Shape>)shapeWithId:(NSString *)Id{ Square *square = [Square new]; square.Id = Id; return square; }
-
执行方法为:
- (id<Shape>)loadShapeWithFactory:(id<ShapeFactory>)factory
- (id<Shape>)loadShapeWithId:(NSString *)Id Factory:(ShapeFactory *)factory{ return [factory shapeWithId:Id]; }
-
通过传入不同的
Factory
,获得不同类型的Shape
。例如:[self loadShapeWithId:@"2" Factory:[CircleFactory new]];
简单工厂方法
在简单工厂中,可以根据参数的不同返回不同类的实例。简单工厂专门定义一个 Factory
类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。例如,删除上面的各个工厂,统一由 ShapeFactroy
类根据遵守Shape
类型的类名反射创建子类的实例。
@interface ShapeFactory : NSObject
+ (id<Shape>)shapeWithId:(NSString *)Id Type:(NSString *)type;
@end
@implementation ShapeFactory
+ (id<Shape>)shapeWithId:(NSString *)Id Type:(NSString *)type{
Class class = NSClassFromString(type);
if ([class conformsToProtocol:@protocol(Shape)]) {
id <Shape>object = [class new];
object.Id = Id;
return object;
}
return nil;
}
@end
可以将简单工厂看为工厂方法模式的一个特例,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
总结
工厂方法是面向对象软件设计中应用非常普遍的设计模式。工厂方法从代码中消除了对应用程序特有类的耦合。代码只需要处理 <Product> 抽象接口,所以同一代码得到复用,在应用程序中与用户定义的任何 ConcreteProduct
实体类一起工作。
网友评论