一,抽象工厂模式
在软件设计过程中,如果客户端需要手动创建一个类的对象,那么客户端需要知道这个类的细节。如果一组相关的对象需要在运行时按照不同的标准创建不一样的对象,那么客户端还需要知道全部细节才可以创建。这是恨糟糕的!
这时可以使用抽象工厂模式,提供一个固定的接口,用于创建一系列有关联或者相依存的对象,而不用指定具体类和细节。这样客户端和从工厂得到的对象之间没有发生耦合。
抽象工厂模式关系类图:
在图中:
AbstractFactory:抽象工厂
ConcreteFactory1,ConcreteFactory2:具体的工厂
AbstractProductA,AbstractProductB:抽象的产品
ProductA1,ProductA2,ProductB1,ProductB2:具体的产品
从图中可以看出,客户端Client只需要知道AbstractFactory和AbstractProduct。在每个工厂类中,结构与实际操作的细节按照黑箱对待。被创建的产品也不清楚谁负责创建自己。只有具体的工厂知道为客户端创建什么,怎么创建。工厂方法把实际创建对象的过程,推迟到子类中进行。
抽象工厂模式,常常和原型模式,单例模式,享元模式一起使用。
二,抽象工厂模式和工厂方法模式
两个模式用于相同的目的:创建对象而不让客户端知道返回了什么具体的对象。
抽象工厂 | 工厂方法 |
通过对象组合创建抽象对象 | 通过类继承创建抽象对象 |
创建多系列产品 | 创建一种产品 |
必须修改父类接口才可以支持新的产品 | 子类化创建者并重载工厂方法创建新的产品 |
软件设计黄金法则:变动需要抽象。
三,代理示例
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface ZGYBrandingFactory : NSObject
+(instancetype)factory;
- (UIView *)brandedView;
- (UIButton *)brandedMainButton;
- (UIToolbar *)brandedToolbar;
@end
#import "ZGYBrandingFactory.h"
#import "ZGYAcmeBrandingFactory.h"
#import "ZGYSierraBrandingFactory.h"
#define USE_ACME 1
@implementation ZGYBrandingFactory
+(instancetype)factory{
#if defined (USE_ACME)
return [[ZGYAcmeBrandingFactory alloc]init];
#elif defined (USE_SIERRA)
return [[ZGYSierraBrandingFactory alloc]init];
#else
return nil;
#endif
}
- (UIView *)brandedView{
return nil;
}
- (UIButton *)brandedMainButton{
return nil;
}
- (UIToolbar *)brandedToolbar{
return nil;
}
@end
#import "ZGYBrandingFactory.h"
@interface ZGYAcmeBrandingFactory : ZGYBrandingFactory
@end
#import "ZGYAcmeBrandingFactory.h"
#import "ZGYAcmeView.h"
#import "ZGYAcmeMainButton.h"
#import "ZGYAcmeToolBar.h"
@implementation ZGYAcmeBrandingFactory
- (UIView *)brandedView{
return [[ZGYAcmeView alloc]init];
}
- (UIButton *)brandedMainButton{
return [[ZGYAcmeMainButton alloc]init];
}
- (UIToolbar *)brandedToolbar{
return [[ZGYAcmeToolBar alloc] init];
}
@end
#import <UIKit/UIKit.h>
@interface ZGYSierraBrandingFactory : UIToolbar
@end
#import "ZGYSierraBrandingFactory.h"
#import "ZGYSierraView.h"
#import "ZGYSierraMainButton.h"
#import "ZGYSierraToolBar.h"
@implementation ZGYSierraBrandingFactory
- (UIView *)brandedView{
return [[ZGYSierraView alloc]init];
}
- (UIButton *)brandedMainButton{
return [[ZGYSierraMainButton alloc]init];
}
- (UIToolbar *)brandedToolbar{
return [[ZGYSierraToolBar alloc] init];
}
@end
客户端使用代码:
#import "ViewController.h"
#import "ZGYBrandingFactory.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ZGYBrandingFactory * factory = [ZGYBrandingFactory factory];
if (factory) {
NSLog(@"%@",[factory class]);
NSLog(@"%@",[[factory brandedView]class]);
NSLog(@"%@",[[factory brandedMainButton]class]);
NSLog(@"%@",[[factory brandedToolbar]class]);
}
}
@end
打印结果
2017-10-07 15:06:51.522565+0800 设计模式(抽象工厂模式)[66543:2920566] ZGYAcmeBrandingFactory
2017-10-07 15:06:51.522862+0800 设计模式(抽象工厂模式)[66543:2920566] ZGYAcmeView
2017-10-07 15:06:51.547872+0800 设计模式(抽象工厂模式)[66543:2920566] ZGYAcmeMainButton
2017-10-07 15:06:51.548153+0800 设计模式(抽象工厂模式)[66543:2920566] ZGYAcmeToolBar
四,cocoa touch框架中的抽象工厂
在cocoa Touch框架中,有很多基础类采用了抽象工厂模式,NSNumber,NSString,NSArray,NSDIctory,NSData。
在NSNumber类中,有各种创建对象的类方法,numberWithBool: numberWithInt:,等等。NSNumber中的各种类工厂方法定义了决定实例化和中具体私有子类的默认行为。这个版本的工厂方法是传统工厂方法的变体,虽然也是返回抽象产品对象,但此处的抽象产品是作为工厂的具体NSNumber子类。NSNumber是抽象工厂方法的一个例子。基础框架中抽象工厂的这个特点被称为“类族”(Class Cluster)