工厂方法(Factory Method)

定义

工厂方法也叫虚构造器(virtual constructor),适用于在代码运行时,当不能确定对象所创建的类型而需要其子类确定的时候。在面向对象编程的环境中,其大致情况就相当于利用多态的特性,调用基类接口创建对象,而子类又各自实现了自己的创建接口的方法,类图结构如下:

如果撇开工厂方法模式的话,那么当需要创建对象的时候,直接在需要的地方使用具体的产品类创建对象即可,但是这样的话代码的粘性(耦合度)就比较高了,不利于后续的代码维护。工厂方法通过增加工厂这一层结构,使得使用的地方的代码不再对产品依赖,而仅仅依赖于对应的工厂,而该工厂又是接口类型的对象,秉承着面向接口的编程风格。

比较正式的工厂方法定义如下所示:

THE FACTORY METHOD PATTERN: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. ** The original definition appeared in
Design Patterns, by the “Gang of Four” (Addison-Wesley,1994).

可以看出该定义主要关注点在让子类自己决定如何创建对象,创建什么类型的对像,工厂方法使得一个对象的实例化延迟到其子类中。也就是说,创建的对象由工厂决定,一旦工厂定了,其创建的产品也就定了。一般而言,工厂方法模式每个产品对应于一个工厂,因此如果增加一个产品的话,就需要增加对应的工厂(这一点比较繁琐的),而需要创建什么样的产品则由指定产品类型变成指定工厂了。工厂方法适用于以下的情况:

  • 代码编译时无法确定对象的具体类型
  • 需要让子类决定创建的对象的类型

代码示例

在很多地方需要用到不同的主题,本例子就是使用主题变化做例子的。其中主题视图是产品,主题视图控制器是工厂,代码的主要文件结构如下所示:

其中CanvasView是默认的产品,ThemeGenerate是工厂的基类,也是负责生产默认产品的类,而PaperCanvasView和ClothCanvasView分别是两个自定义的产品,同时也为这个两个产品分别构建了对应的工厂类,其类图如下所示:

由于使用的时候,代码是直接和工厂打交道的,而工厂类又有相同的接口,所以,产品接口可以不一样,三个产品的定义分别如下所示:

#import "CanvasView.h"

@implementation CanvasView

- (id)init
{
    if(self = [super init])
    {
        // 设置默认颜色
        self.backgroundColor = [UIColor whiteColor];
    }
    return self;
}

@end
#import "ClothCanvasView.h"

@implementation ClothCanvasView
- (id)init
{
    if(self = [super init])
    {
        self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"cloth.jpg"]];
    }
    return self;
}
@end
#import "PaperCanvasView.h"

@implementation PaperCanvasView

- (id)init
{
    if(self = [super init])
    {
        self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"paper.jpg"]];
    }
    return self;
}

@end

上述三个类分别创建了不同颜色背景的视图,现在需要其对应的工厂类,工厂类之间有继承关系的。

#import "ThemeGenerate.h"

@implementation ThemeGenerate
- (CanvasView *) canvasView
{
    // 默认的工厂方法返回默认的主题(产品)
    return [[CanvasView alloc] init];
}
@end
#import "ClothThemeGenarate.h"
#import "ClothCanvasView.h"

// 继承自 ThemeGenerate
@implementation ClothThemeGenarate
- (CanvasView *) canvasView
{
    // 创建Cloth主题产品
    return [[ClothCanvasView alloc] init];
}
@end
#import "PaperThemeGenarate.h"
#import "PaperCanvasView.h"

// 继承自 ThemeGenerate
@implementation PaperThemeGenarate
- (CanvasView *) canvasView
{
    // 创建Paper主题产品
    return [[PaperCanvasView alloc] init];
}
@end

没个工作类负责生产一种产品,同时对外提供统一的接口,这样客户端都可以通过该接口要求获取全部的产品,其调用的地方如下所示

- (IBAction)changeTheme:(id)sender
{
    [_theme removeFromSuperview];

    ThemeGenerate* newTheme = nil;
    if (sender == _clothTheme)
    {
        newTheme = [[ClothThemeGenarate alloc] init];
    }
    else if(sender == _paperTheme)
    {
        newTheme = [[PaperThemeGenarate alloc] init];
    }
    else
    {
        newTheme = [[ThemeGenerate alloc] init];
    }
    _theme = newTheme.canvasView;
    _theme.frame = self.view.frame;
    [self.view insertSubview:_theme atIndex:0];
}

客户端直接通过调用接口canvasView即可获得自己想要的产品,如果想增加一类产品的话,直接创建一个产品和工厂类即可,修改代码较小。

总结

工厂方法可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。

时间: 2024-10-11 16:47:46

工厂方法(Factory Method)的相关文章

Spring 通过工厂方法(Factory Method)来配置bean

Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. 在第一种利用bean config file(spring xml)方式中, 还包括如下三小类 反射模式 工厂方法模式(本文重点) Factory Bean模式 其中反射模式最常见, 我们需要在bean 配置中指明我们需要的bean object的全类名. 例如: <bean id="car1

设计模式二: 工厂方法(Factory Method)

设计模式二: 工厂方法(Factory Method) 简介 工厂方法模式是创建型模式的一种, 核心结构有四个角色: 抽象工厂,具体工厂,抽象产品,具体产品; 实现层面上,该模式定义一个创建产品的接口,将实际创建工作推迟到具体工厂类实现, 一个产品对应一个工厂, 这样的好处是当有新产品引入时可以不修改具体的工厂角色. 意图 定义了一个创建对象的接口,但由子类决定要实例化哪个类.工厂方法把实例化操作推迟到子类. 类图 实现 以汽车举例. 按照本模式核心的四个角色分别定义, 并增加模式调用角色(此处

工厂方法 Factory Method

背景:有一个应用框架,它可以向用户显示多个文档.在这个框架中,两个主要的抽象是类Application和Document.这两个类都是抽象的.客户必须通过它们的子类来做与举替应用相关的实现. 分析:因为被实例化的特定Document子类是与特定应用相关的,所iApplication类不可能预测到那个Document子类将被实例化一一Application类仅直到一个新的文档何时应被创建,而不知道哪一种Document将被创建.这就产生了一个尴尬的局面框架必须实例化类,但是它只知道不能被实例化的抽

设计模式 笔记 工厂方法 Factory Methon

//---------------------------15/04/09---------------------------- //factory method 工厂方法-------对象创建型模式 /* 1:意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. Factory Method使一个类的实例化延迟到其子类. 2:别名: 虚构造器(virtual constructor) 3:动机: 4:适用性: 1>当一个类不知道它所必须创建的对象的类的时候. 2>当一个类希望由它

工厂方法模式(FACTORY METHOD)

核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦.复用和方便后期维护拓展的目的. 工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.使一个类的实例化延迟到其子类. 核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂 角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品. 简单工厂模式跟工厂方法模式区别是:简单工厂

工厂方法模式 Factory Method

工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品. #include <iostream> using namespace std; class Fruit{ public: virtual void show()=0; }; class App

JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)

简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实现添加新产品而不影响已有代码?工厂方法模式应运而生,本文将介绍另外一种工厂模式--工厂方法模式. 1 日志记录器的设计 Sunny软件公司欲开发一个系统执行日志记录器(Logger).该记录器能够通过多种途径保存系统的执行日志,如通过文件记录或数据库记录,用户能够通过改动配置文件灵活地更换日志记录方式. 在设

设计模式之工厂方法模式

anticipate 预料 = except ant蚂蚁 ic ic卡 ip ip卡 ate吃 我没有预料到小蚂蚁把我的ic,ip卡吃掉了. robust 强壮的 = strong ro rong容祖儿  bu不  st石头 容祖儿不喜欢强壮的石头. maintain 维持 = keep main主要的(大陆)  tain 台湾 大陆和台湾维持着若即若离的关系. 设计模式之工厂方法模式 动机:     一个工厂方法factory method定义了一个接口来创建对象,但是让子类去选择创建哪一个,

工厂模式(Factory Patter)

1.工厂模式简介 工厂模式属于创建型模式,是专门用来创建对象的模式,抽象了实例化的过程.工厂模式分为 : 工厂方法模式.抽象工厂模式. 在学习工厂方法模式.抽象工厂之前,首先先要了解一下简单工厂模式,简单工厂不在23种设计模式之列,一般它是根据自变量的不同而返回不同的类型.比较简单实用一些,在学习工厂模式之前下来学习一下简单工厂,有助于我们理解工厂模式. 1.1.简单工厂定义 简单工厂是由一个工厂对象决定创建出哪一种产品类的实例. 其实质就是由一个工厂类根据传入的参数,来决定调用哪一个产品类的实

工厂模式(factory pattern)

工厂模式主要用来封装对象的创建,有3种分类:简单工厂(simple factory).工厂方法(factory method).抽象工厂(abstract factory). 简单工厂包括3种组成元素:抽象产品.具体产品.具体工厂(简单工厂),结构图如下: C++实现: //抽象产品 class Car { public: virtual string getDescription() = 0; }; //具体产品 class Audi : public Car { string getDesc