首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >设计模式:工厂方法模式

设计模式:工厂方法模式

作者头像
王强
发布于 2018-08-09 09:25:49
发布于 2018-08-09 09:25:49
53801
代码可运行
举报
文章被收录于专栏:Python爬虫实战Python爬虫实战
运行总次数:1
代码可运行

1 概述

工厂方法(Factory Method)模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。 在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而子类负责生成具体产品对象,这样做的目的是将产品类的实例化延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

2 图解

现在有A、B、C三种产品,相对应的有三个工厂:工厂A负责生产A产品,工厂B负责生产B产品,工厂C负责生产C产品。这时候客户不需要告诉工厂生产哪种产品了,只需要告诉对应的工厂生产就可以了。

图解工厂模式

工厂方法模式包含如下角色:

  • Factory 抽象工厂角色: 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
  • ConcreteFactory 具体工厂角色(图中的FactoryA、FactoryB、FactoryC) 实现抽象工厂接口的具体工厂类,被应用程序调用以创建产品对象。
  • Product 抽象产品角色: 抽象产品角色是所创建所有对象的父类,负责描述所有实例的公共接口。
  • ConcreteProduct 具体产品角色(图中的ProductA、ProductB、ProductC): 实现了抽象产品角色所定义的接口 ,由专门的具体工厂角色创建。

3 优缺点

优点:

  • 子类提供挂钩。基类为工厂方法提供缺省实现,子类可以重写新的实现,也可以继承父类的实现。-- 加一层间接性,增加了灵活性
  • 屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,只需关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。
  • 典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。
  • 多态性:客户代码可以做到与特定应用无关,适用于任何实体类。

缺点:

  • 添加新产品时,需要编写新的具体产品类 ,而且还要提供与之对应的具体工厂类,系统中类的将成对增加,在一定程度上增加了系统的复杂度。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

4 应用场景

如果一个对象拥有很多子类,那么创建该对象的子类使用工厂模式是最合适的,不但可以面向接口的编程,为维护以及开发带来方便。

如果创建某个对象时需要进行许多额外的操作,如查询数据库然后将查询到的值赋予要创建的对象(单例初始化时使用比较多),或是需要许多额外的赋值等等。如果查看JDK源码中,会发现许多成员变量在对象构造时,通过工厂方法进行创建的。因为这些成员变量本身的创建也很复杂。不可能创建对象时,在该对象的构造方法里创建成员变量然后再赋值给该成员变量。而且使用工厂模式也提高了代码的重用性。

5 实例

FactoryMethodUml

5.1 C++实现

  • product.h
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef PRODUCT_H
#define PRODUCT_H

#include <iostream>

// 产品基类
class Product
{
public:
    Product() {}
    virtual ~Product(){}

    virtual void detail() const
    {
        std::cout << "This is the base class of product." << std::endl;
    }
};

// 产品A
class ProductA : public Product
{
public:
    ProductA() {}
    ~ProductA() {}

    virtual void detail() const
    {
        std::cout << "This is ProductA." << std::endl;
    }
};

// 产品B
class ProductB : public Product
{
public:
    ProductB() {}
    ~ProductB() {}

    virtual void detail() const
    {
        std::cout << "This is ProductB." << std::endl;
    }
};

// 产品C
class ProductC : public Product
{
public:
   ProductC() {}
   ~ProductC() {}

    virtual void detail() const
    {
        std::cout << "This is ProductC." << std::endl;
    }
};

#endif // PRODUCT_H
  • factory.h
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef FACTORY_H
#define FACTORY_H

#include "product.h"

// 工厂基类
class Factory
{
public:
    Factory(){}
    virtual ~Factory(){}

    static Product* produce()
    {
        return NULL;
    }
};

// 工厂A
class FactoryA : public Factory
{
public:
    FactoryA();
    virtual ~FactoryA();

    static Product* produce()
    {
        return new ProductA();
    }
};

// 工厂B
class FactoryB : public Factory
{
public:
    FactoryB();
    virtual ~FactoryB();

    static Product* produce()
    {
        return new ProductB();
    }
};

// 工厂C
class FactoryC : public Factory
{
public:
    FactoryC();
    virtual ~FactoryC();

    static Product* produce()
    {
        return new ProductC();
    }
};

#endif // FACTORY_H
  • main.cpp
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>

#include "factory.h"

using namespace std;

int main()
{
    Product* productA = NULL;
    productA = FactoryA::produce();
    productA->detail();
    cout << "==============" << endl;

    Product* productB = NULL;
    productB = FactoryB::produce();
    productB->detail();
    cout << "==============" << endl;

    Product* productC = NULL;
    productC = FactoryC::produce();
    productC->detail();
    cout << "==============" << endl;

    delete productA;
    delete productB;
    delete productC;

    return 0;
}

运行结果

运行结果

5.2 Python实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#-*- coding: utf-8 -*-

'''
  工厂模式
'''

class Product:
    '''
    产品基类
    '''
    def detail(self):   
        print('This is the base class of produce')

class ProductA(Product):
    '''
    产品A
    '''
    def detail(self):   
        print('This is ProductA.')

class ProductB(Product):
    '''
    产品B
    '''
    def detail(self):   
        print('This is ProductB.')

class ProductC(Product):
    '''
    产品C
    '''
    def detail(self):   
        print('This is ProductC.')

class Factory:
    '''
    工厂类
    '''
    def produce(self):
        return None

class FactoryA(Factory):
    '''
    工厂A
    '''
    def produce(self):
        return ProductA()

class FactoryB(Factory):
    '''
    工厂B
    '''
    def produce(self):
        return ProductB()

class FactoryC(Factory):
    '''
    工厂C
    '''
    def produce(self):
        return ProductC()

def main():
    factoryA = FactoryA()
    productA = factoryA.produce()
    productA.detail()
    print('==================')
    factoryB = FactoryB()
    productB = factoryB.produce()
    productB.detail()
    print('==================')
    factoryC = FactoryC()
    productC = factoryC.produce()
    productC.detail()
    print('==================')

if __name__ == '__main__':
    main()

运行结果:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 C与Python实战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java8的双绝学之一stream能用来做什么?
Java 8 是一个非常成功的版本,Java8 新增的Stream,配合同版本出现的 Lambda ,给我们操作集合提供了极大的便利。
冷环渊
2021/12/14
7070
Java8的双绝学之一stream能用来做什么?
Java8新特性之Stream流(含具体案例)
Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminal operation) 得到前面处理的结果。Stream 流可以极大的提高开发效率,也可以使用它写出更加简洁明了的代码。我自从接触过 Stream 流之后,可以说对它爱不释手。
军军不吃鸡
2022/10/26
2.8K1
Java8新特性之Stream流(含具体案例)
强大的 Stream API(三)
终端操作会从流的流水线生成结果。其结果可以是任何不是流的 值,例如:List、Integer,甚至是 void 。
IT小马哥
2020/10/27
3940
Java 8新特性
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。
用户9615083
2022/12/25
1.5K0
Java 8新特性
Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合
Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。
云深i不知处
2020/11/12
3.7K0
Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合
Java8 Stream常用API整理(值得收藏)
来 源:https://blog.csdn.net/wangchengming1/article/details/89245402
一个程序员的成长
2020/11/25
5440
Stream流你学会了吗?
Steam流 1. 创建Stream流的方式 创建一个Stream流 进行数据操作 终止操作 1.1 如何创建Stream流 Collection提供的两个方法stream()和parallelStream() stream()流获取的是一个顺序流 parallelstream()获取一个并行流 Set<String> set = new HashSet<>(); Stream<String> stream = set.stream(); Stream<String> stringStream = set.
石的三次方
2021/01/05
1.6K0
【小家java】java8新特性之---Stream API 详解 (Map-reduce、Collectors收集器、并行流、groupby多字段分组)
Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。
YourBatman
2019/09/03
3.3K0
【小家java】java8新特性之---Stream API 详解  (Map-reduce、Collectors收集器、并行流、groupby多字段分组)
Java 8 Stream常用方法学习
Stream流是 Java8 API 新增的一个处理集合的关键抽象概念,是一个来自数据源的元素队列并支持聚合操作。以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
全栈程序员站长
2022/11/09
1.2K0
Java 8 Stream常用方法学习
java8新特性(二):StreamAPI
Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一个则是Stream API(java.util.stream.*)。 Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
周三不加班
2019/09/03
5840
java8新特性(二):StreamAPI
【Java基础-1】 Java8新特性Stream详解
Java8的API中添加了一个新的特性: 流,即stream。stream是将数组或者集合的元素视为流,流在管道中流动过程中,对数据进行筛选、排序和其他操作。
云深i不知处
2020/09/16
1.2K0
JDK8中的新特性(Lambda、函数式接口、方法引用、Stream)
<font color=red>Java 8</font> (又称为 JDK 8或JDK1.8) 是 Java 语言开发的一个主要版本。 Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。
鱼找水需要时间
2023/06/01
9080
JDK8中的新特性(Lambda、函数式接口、方法引用、Stream)
Stream API学习笔记
  Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
程序员波特
2024/01/19
1660
JDK8 超详细,肝
Lambda表达式:依赖于函数式接口, 是对函数式接口的,另一种:实例化形式~👍 更简洁,难懂🙃
Java_慈祥
2024/08/06
3590
JDK8 超详细,肝
Java Stream流
stream是顺序流,由主线程按顺序对流执行操作; parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,如果对流中的数据处理没有顺序要求就可以使用并行流。(一般不建议使用并行流,不熟悉的话很容易踩坑,使用情况经常是弊大于利) 例如筛选集合中的奇数,两者的处理不同之处:
十玖八柒
2022/08/01
3.1K1
Java Stream流
JDK8新特性-Stream流[通俗易懂]
作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门。
全栈程序员站长
2022/11/10
5470
Java8 Stream
Java Stream函数式编程接口最初是在Java 8中引入的,并且与lambda一起成为Java开发的里程碑式的功能特性,它极大的方便了开放人员处理集合类数据的效率。
HLee
2021/08/12
1.7K0
Java8 Stream
一文带你玩转Java8Stream,从此集合操作SoEasy
但是,偶尔我们也有这种需求,需要将常规对象流转换为原始类型流,这个时候,中间操作 mapToInt(),mapToLong() 以及mapToDouble就派上用场了
九转成圣
2024/04/10
2910
Java中的Stream API简述
小尘要自信
2023/10/10
2520
Java 8 Stream API学习总结
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
冯文议
2020/05/16
1.2K0
Java 8 Stream API学习总结
相关推荐
Java8的双绝学之一stream能用来做什么?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档