意图:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。

其实在抽象工厂模式中,经过改进后的模式就是工厂方法模式,所以不多说了,上UML图。

通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:

1.工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类作为与调用者交互的接口,其本质上是一样的。

2.工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。

3.产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。

4.产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。

前文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱,可以算作工厂方法模式的简化版

举例说明:

还是举生产产品的例子吧。一个工厂生产A,B两种产品,以后还可能会拓展生产C产品,怎么安排类的设计模式使得以后的拓展或者用户额调用更加方便——工厂方法模式。

//定义工厂方法所创建的对象的接口
#ifndef _PRODUCT_H
#define _PRODUCT_H class Product
{
protected:
Product(){}
public:
virtual ~Product(){}
virtual void function() = 0;
};
#endif //实现Product接口
#ifndef _CONCRETE_PRODUCT_A_H
#define _CONCRETE_PRODUCT_A_H #include "Product.h"
#include <iostream>
using namespace std; class ConcreteProductA : public Product
{
public:
ConcreteProductA()
{
cout<<"创建产品A"<<endl;
} virtual ~ConcreteProductA()
{
cout<<"销毁产品A"<<endl;
} virtual void function()
{
cout<<"这是产品A的功能"<<endl;
} };
#endif //实现Product接口
#ifndef _CONCRETE_PRODUCT_B_H
#define _CONCRETE_PRODUCT_B_H #include "Product.h"
#include <iostream>
using namespace std; class ConcreteProductB : public Product
{
public:
ConcreteProductB()
{
cout<<"创建产品B"<<endl;
} virtual ~ConcreteProductB()
{
cout<<"销毁产品B"<<endl;
} virtual void function()
{
cout<<"这是产品B的功能"<<endl;
} };
#endif //声明工厂方法,该方法返回一个Product类型的对象
#ifndef _CREATER_H
#define _CREATER_H class Creator
{
public:
Creator(){}
virtual ~Creator(){}
virtual Product *CreateProduct(int type=0) = 0;//参数化工厂方法
};
#endif //重定义工厂方法以返回一个ConcreteProduct实例
#ifndef _CONCRETE_CREATOR_H
#define _CONCRETE_CREATOR_H #include "ConcreteProductA.h"
#include "ConcreteProductB.h"
#include "Product.h"
class ConcreteCreator : public Creator
{
public:
ConcreteCreator(){}
virtual ~ConcreteCreator(){}
virtual Product *CreateProduct(int type)
{
Product *product;
switch(type)
{
case 0:
product = new ConcreteProductA();
break;
case 1:
product = new ConcreteProductB();
break;
default:
product = new ConcreteProductA();
break;
}
return product;
} };
#endif 客户端程序:
#include "Product.h"
#include "ConcreteProductA.h"
#include "ConcreteProductB.h"
#include "Creator.h"
#include "ConcreteCreator.h" int main(int argc, char **argv)
{
Creator *c = new ConcreteCreator();
Product *p = c->CreateProduct(0);
p->function();
delete p;
delete c; system("pause");
return 0;
}

当我们的系统需要增加其他新的对象时,我们只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,这样很好地符合了“开闭原则”。

工厂方法适用场景

1、一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。

2、一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。

3.3FactoryMethod——工厂方法的更多相关文章

  1. 工厂方法模式——创建型模式02

    1. 简单工厂模式     在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...

  2. 设计模式C#合集--工厂方法模式

    简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...

  3. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  4. javascript设计模式-工厂方法模式

    工厂方法模式笔记  通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例  对于创建多类对象,简单工厂不太实用,这是简单工厂模式的应用局限,当然这正是工厂方法模式的价值之所在  通过工厂方法模 ...

  5. C#设计模式(3)——工厂方法模式

    一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...

  6. OC编程之道-创建对象之抽象工厂方法

    定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类.       <AbstractProductA> <AbstractProductB> <Ab ...

  7. Spring学习记录(九)---通过工厂方法配置bean

    1. 使用静态工厂方法创建Bean,用到一个工厂类 例子:一个Car类,有brand和price属性. package com.guigu.spring.factory; public class C ...

  8. C#设计模式系列:工厂方法模式(Factory Method)

    1. 工厂方法模式简介 1.1 定义 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法模式是以一个类的实例化延迟到其子类. Factory Method模式用于在不指定待创建 ...

  9. 小菜学习设计模式(三)—工厂方法(Factory Method)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

随机推荐

  1. silverlight5开发的翻牌游戏

    扑克牌用了一个自定义控件,代码如下 public class CardButton : Button { public int state;//是否翻转0是未翻转,1是已翻转 private stat ...

  2. Nth Digit | leetcode

    Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... Note: n i ...

  3. Xcode8和iOS10的适配问题

    本文转自:http://www.jianshu.com/p/90d5323cf510 =================== 一.遇到的问题 1.权限以及相关设置 iOS10系统下调用系统相册.相机功 ...

  4. [BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】

    题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于 ...

  5. BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会

    Description Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来举办这次集会.每个奶牛居住在 N(1<=N<=100,0 ...

  6. 李洪强iOS开发Swift篇—08_函数(2)

    李洪强iOS开发Swift篇—08_函数(2) 一.函数类型 函数类型也是数据类型的一种,它由形参类型和返回值类型组成,格式是 (形参类型列表) -> 返回值类型 1 func sum(num1 ...

  7. 编译Firebird的源码

    编译步骤:一.下载所需的软件  1.下载FB2.0 RC4       http://optusnet.dl.sourceforge.net/sourceforge/firebird/Firebird ...

  8. 一个优秀的http实现框架

    package com.ming; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unir ...

  9. 新一批电子商务解决方案和企业管理应用加入 VM Depot 中国站点

     新一批电子商务解决方案和企业管理应用加入 VM Depot 中国站点. //电子商务平台助力您建设网店// 大约有 6 个最近更新的电子商务程序包已经登陆 VM Depot. 这不仅囊括了全球知 ...

  10. Centos6.4 设置开机自动以某个非root用户启动脚本

    开机自动运行脚本,可以将脚本的执行命令放在 /etc/rc.d/rc.local 文件中,但是这样开机自动运行这个脚本的用户默认为root. 如果想以某个非root用户运行脚本,可以使用如下命令: s ...