抽象工厂(Abstract Factory)(一)

2015-01-22 20:51:25 · 作者: · 浏览: 21

定义

在软件设计中,如果客户想手动创建一个对象,需要知道对象的详细结构,包括其数据结构以及方法调用,如果运气不好,还可能因为该对象引用了其他对象,导致客户端还得了解其他对象,如此..使得该对象的创建变得复杂起来。之前讲过的工厂方法模式可以解决该类问题,不过工厂方法模式一般用来解决单个对象的创建,对于需要创建多个有关联的对象,那么可能就需要使用抽象工厂模式的方法了。此时,客户端只需要知道抽象出来的工厂以及自己所要的对象即可,不必清楚是谁创建以及怎样创建那些具体的对象。


抽象工厂的具体定义为:抽象工厂提供固定的接口,用于创建一系列有关联的对象,而不必指出其创建的细节。

ABSTRACT FACTORY: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.*

* The original definition appeared in Design Patterns, by the “Gang of Four” (Addison-Wesley,1994).

其类似的类图示意图可能如下所示

\

上述的类图示意图中,如果客户端想创建产品A和B,他只需要知道抽象工厂的固定接口createProductA和createProductB(当然还得知道AbstractFactory、AbstractProductA和AbstractProductB的存在),这样他就能够直接使用这两个接口创建自己所需要的产品A和B了,而不需要知道产品A和B是谁创建的,在哪创建以及其他细节问题。通过抽象工厂的封装,使得有关联的对象的创建变得透明、简单化。

此外,通过抽象工厂模式的编程方法,你如果后续想添加其他产品,则直接按照定好的抽象工厂接口实现即可,而不需要改变客户端的代码调用。

在这里还得补充一点关于工厂方法和抽象工厂的关系问题,上图中,抽象工厂是有包含工厂方法的设计模式的,其中createProductA和createProductB都属于工厂方法,更多的比较可见下表:

工厂方法和抽象工厂
抽象工厂 工厂方法
通过对象组合创建产品 通过类继承创建产品
创建一类有关联的产品,包括多种产品 创建一种产品
如果新增产品类型,必须修改抽象类的固定接口 子类化创建者并重载工厂方法以创建新产品


代码示例

还是用主题来做个例子吧,这个例子是一个界面主题,该主题包括三部分:主视图,按钮,工具栏,不同的主题,这些元素的样式不一样,其他的是一样的。因此由此可抽象出一个抽象工厂类,该类提供的固定接口是三个创建对象的方法,分别用来创建主视图、按钮和工具栏。主要的关系图如下所示:

\

抽象类的定义如下所示:

#import 
  
   
#import 
   
     @interface BrandFactory : NSObject + (BrandFactory*)fatoryWithName:(NSString*)name; - (UIView*) brandView; - (UIButton*) brandMainButton; - (UIToolbar*) brandToolbar; @end
   
  
上述代码定义了三个固定的接口,而类方法fatoryWithName则会根据名字选择对应的工厂。其中三个固定接口在抽象工厂类返回值是nil,而其中的类方法其实现如下所示:
+ (BrandFactory*)fatoryWithName:(NSString*)name
{
    BrandFactory* factory = nil;
    if([name isEqualToString:@"Serra"])
    {
        factory = [[SerraBrandFactory alloc] init];
    }
    else if([name isEqualToString:@"Acme"])
    {
        factory = [[AcmeBrandFactory alloc] init];
    }
    return factory;
}

对应于上图的关系图,实现的两个具体工厂类如下所示:

@implementation SerraBrandFactory
- (UIView*) brandView
{
    UIView* view = [[UIView alloc] init];
    view.backgroundColor = [UIColor redColor];
    return view;
}
- (UIButton*) brandMainButton
{
    UIButton* button = [[UIButton alloc] init];
    [button setTitle:@"Serra" forState:UIControlStateNormal];
    return button;
}
- (UIToolbar*) brandToolbar
{
    UIToolbar* toolbar = [[UIToolbar alloc] init];
    toolbar.barStyle = UIBarStyleBlack;
    
    UIBarButtonItem* item = [[UIBarButtonItem alloc] init];
    [item setImage:[UIImage imageNamed:@"cat.png"]];
    
    toolbar.items = [NSArray arrayWithObject:item];
    
    return toolbar;
}
@end

@implementation AcmeBrandFactory
- (UIView*) brandView
{
    UIView* view = [[UIView alloc] init];
    view.backgroundColor = [UIColor blueColor];
    return view;
}
- (UIButton*) brandMainButton
{
    UIButton* button = [[UIButton alloc] init];
    [button setTitle:@"Acme" forState:UIControlStateNormal];
    return button;
}
- (UIToolbar*) brandToolbar
{
    UIToolbar* toolbar = [[UIToolbar alloc] init];
    toolbar.barStyle = UIBarStyleBlack;
    
    UIBarButtonItem* item = [[UIBarButtonItem alloc] init];
    [item setImage:[UIImage imageNamed:@"dog.png"]];
    
    toolbar.items = [NSArray arrayWithObject:item];
    
    return toolbar;
}
@end
上两个实现分别返回自身定制的产品对象,而且都是通过基类抽象工厂类的固定接口返回的,这样当客户端需要构建这些对象的时候,直接使用抽象工厂提供的接口即可完成对所需的对象的创建,客户端冻得代码调用如下所示:
- (void)viewDidLoad 
{
    [super viewDidLoad];
    // Do any additional setup a