设计模式学习(七):Factory Method工厂模式

news2024/11/15 17:18:29

目录

一、什么是Factory Method模式

 二、Factory Method示例代码

2.1 类之间的关系

2.2 Product类

2.3 Factory类

2.4 IDCard类

2.5 IDCardFactory类

2.6 用于测试的Main类

2.7 运行结果

三、拓展思路的要点

3.1 框架与具体加工

3.2 使用模式与开发人员之间的沟通

四、相关的设计模式

4.1 Template Method模式

4.2 Singleton模式

4.3 Composite模式

4.4 lterator模式


一、什么是Factory Method模式

        在Template Method模式中,我们在父类中规定处理的流程,在子类中实现具体的处理。如果我们将该模式用于生成实例,它就演变为本章中我们所要学习的Factory Method模式。

        想先了解Template Method,可以看我的博客:设计模式学习(六):Template Method模板方法模式_玉面大蛟龙的博客

        Factory有“工厂”的意思。用Template Method模式来构建生成实例的工厂,这就是Factory Method模式。

        在Factory Method模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理全部交给子类负责。这样就可以将生成实例的框架( framework )和实际负责生成实例的类解耦。

        用一句话来概括:将实例的生成交给子类。

 二、Factory Method示例代码

        这段示例程序的作用是制作身份证(ID卡),它其中有5个类(图4-1)。

        Product类和Factory类属于framework包。这两个类组成了生成实例的框架。IDCard类和 IDCardFactory类负责实际的加工处理,它们属于idCard包。Main类是用于测试程序行为的类。

        之所以将他们分为不同的包,是因为如果我们想再生产其他的产品,比如创建电视机类和电视机工厂类,只需要引入framework包,只编写television包即可。

        因此在阅读示例程序时,请注意所阅读的代码属于framework包还是idcard包。

2.1 类之间的关系

        先看一下所有的类:

        类图:


2.2 Product类

        framework 包中的Product类是用来表示“产品”的类。在该类中仅声明了use抽象方法。use方法的实现则被交给了Product类的子类负责。

        在这个框架中,定义了产品是“任意的可以use的”的东西。 

package framework;

public abstract class Product {
    public abstract void use();
}

2.3 Factory类

        在framework包中的Factory类中,我们使用了Template Method模式。该类还声明了用于“生成产品”的createProduct抽象方法和用于“注册产品”的registerProduct抽象方法。"生成产品”和“注册产品”的具体处理则被交给了Factory类的子类负责。

        在这个框架中,我们定义了工厂是用来“调用create方法生成Product实例”的。而create方法的实现是先调用createProduct生成产品,接着调用registerProduct注册产品。

        具体的实现内容根据Factory Method模式适用的场景不同而不同。但是,只要是FactoryMethod模式,在生成实例时就一定会使用到Template Method模式。

        在示例程序中,createProduct方法是用于生成实例的方法。不用new关键字来生成实例,而是调用生成实例的专用方法来生成实例,这样就可以防止父类与其他具体类耦合。 

package framework;

public abstract class Factory {
    public final Product create(String owner) {
        Product p = createProduct(owner);
        registerProduct(p);
        return p;
    }

    protected abstract void registerProduct(Product product);

    protected abstract Product createProduct(String owner);
}

2.4 IDCard类

        之前我们已经理解了框架( framework包)的代码。接下来让我们把关注点转移到负责加工处理的这一边(idcard包)。

        我们先来编写表示ID卡的类,即IDCard类。为了能够明显地体现出与框架的分离,我们将这个类放在idcard包中。IDCard类是产品 Product类的子类。

        需要注意的一点是:我们并没有把IDCard的构造函数声明为public类型,这是想让idcard包外的类无法new出 IDcard 类的实例。这样就可以强迫外部必须通过IDCardFactory来生成IDCard的实例(在Java中,只有同一个包中的类可以访问不带public、protected、private等修饰符的构造函数和方法)。

package idcard;

public class IDCard extends Product {

    private String owner;

    IDCard(String owner) {
        System.out.println("制作" + owner + "的ID卡。");
        this.owner = owner;
    }

    @Override
    public void use() {
        System.out.println("使用" + owner + "的ID卡。");
    }

    public String getOwner() {
        return owner;
    }
}

2.5 IDCardFactory类

package factoryMethod.idcard;

public class IDCardFactory extends Factory {

    //IDCard的各个持有人
    private List owners = new ArrayList();

    //生产产品,即生成IDCard的实例
    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }

    //注册产品,即把各个产品的持有人保存到owners中
    protected void registerProduct(Product product) {
        owners.add(((IDCard)product).getOwner());
    }

    public List getOwners() {
        return owners;
    }
}

2.6 用于测试的Main类

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product card1 = factory.create("小明");
        Product card2 = factory.create("小红");
        Product card3 = factory.create("小刚");
        card1.use();
        card2.use();
        card3.use();
    }
}

2.7 运行结果

 

三、拓展思路的要点

3.1 框架与具体加工

        至此,我们分别学习了“框架”与“具体加工”这两方面的内容。它们分别被封装在framework包和idcard包中。

        这里,让我们用相同的框架创建出其他的“产品”和“工厂”。例如,我们这次要创建表示电视机的类Televison和表示电视机工厂的类TelevisonFactory。这时,我们只需要引入( import ) framework包就可以编写televison包。

3.2 使用模式与开发人员之间的沟通

        不论是我们在之前学习的Template Method模式还是本文中学习的Factory Method模式,在实际工作中使用时,都会让我们感觉到比较困难。这是因为,如果仅阅读一个类的代码,是很难理解这个类的行为的。必须要理解父类中所定义的处理的框架和它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才行。

        通常,使用设计模式设计类时,必须要向维护这些类的开发人员正确地传达设计这些设计模式的意图。否则,维护人员在修改设计时可能会违背设计者最初的意图。

        这时,我们建议在程序注释中和开发文档中记录所使用的设计模式的名称和意图。

四、相关的设计模式

4.1 Template Method模式

        Factory Method模式是Template Method的典型应用。在示例程序中,create方法就是模板方法。

        设计模式学习(六):Template Method模板方法模式_玉面大蛟龙的博客-CSDN博客

4.2 Singleton模式

        在多数情况下我们都可以将Singleton模式用于扮演Creator角色(或是ConcreteCreator角色)的类。这是因为在程序中没有必要存在多个Creator角色(或是ConcreteCreator角色)的实例。不过在示例程序中,我们并没有使用Singleton模式。

4.3 Composite模式

        有时可以将Composite模式用于Product角色(或是ConcreteProduct角色 )。

4.4 lterator模式

        有时,在 Iterator模式中使用iterator方法生成Iterator的实例时会使用Factory Method模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(12)go-micro微服务JWT跨域认证

文章目录一 JWT介绍二 JWT优缺点三 JWT使用1. 导包和数据定义2.生成JWT3.解析JWT4.完整代码四 最后一 JWT介绍 JWT 英文名是 Json Web Token ,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。 JWT 以 JS…

拐点检测常用算法总结

目录概览问题定义符号定义研究方法损失函数概览 问题定义 拐点检测名为 change point detection,对于一条不平缓的时间序列曲线,认为存在一些时间点 (t1,t2,...,tk)( t_1 , t_2 , . . . , t_k )(t1​,t2​,...,tk​) ,使得曲线在这些点对应…

Java SPI的介绍、JDBC中SPI的应用、自己实现一个SPI应用

目录1. Java SPI介绍2. Java SPI的运行流程3. Java SPI在JDBC中的应用4. Java SPI的三大规范要素5. 自己实现一个SPI应用5.1 Service接口5.2 运营商1的Service Provider5.3 运营商2的Service Provider5.3 手机使用网络1. Java SPI介绍 SPI(Service Provider Interface)是一种基…

在别墅大宅中打造全屋智能,总共需要几步?

关于智能家居,很多读者可能会想起一些不那么愉快的回忆:2014年左右的智能家居浪潮,涌现出了众多带蓝牙互联功能的家电产品,但数据无法互联互通、单品体验升级有限,加上一些企业竞争失败产品不再更新,留给消…

EXCEL工具介绍

目录1. 锁定功能2. 固定1. 锁定功能 锁定:F4 公式引用单元格,有“相对引用”与“绝对引用” 美元符号“ $ ”在excel公式中的作用是在“绝对引用”时,锁定行号或列标(单元格地址由列标行号组成,如A1,A为列…

国产软件不惧微软,WPS力扛大旗,新型办公软件争相助力

金山作为程序员的“黄埔军校”,输入了一批批互联网大佬,小米的雷军、哔哩哔哩的陈睿、蓝港互动的王峰等都师出金山。WPS作为金山拳头作品,有着“国民软件”美誉,功能强大,使用体验一点不输微软word,然而有一…

打工人必学的法律知识(三)——《中华人民共和国劳动争议调解仲裁法》

PS : 对与日常工作比较紧密的部分做摘录 中华人民共和国劳动争议调解仲裁法http://www.npc.gov.cn/npc/c198/200712/756d4eceb95e420a87c97545a58d931c.shtml 目录 一、调解 二、仲裁 三、申请和受理 四、开庭和裁决 五、附则 第六条 发生劳动争议&#xff0…

python镜像设置

winr 输入 %USERPROFILE% 新建pip目录,目录内新建pip.ini 输入: [global] index-urlhttp://mirrors.aliyun.com/pypi/simple/ trusted-hostmirrors.aliyun.com

计算机网络概括

1 前言计算机网络是指将位于不同地理位置,但具有独立功能的多台设备,通过通信设备和线路连接起来,在网络操作系统,网络管理软件、网络通信协议的协调管理下,实现资源共享和信息传递的计算机系统。简单来说,…

STM32模拟SPI总线读写RFID模块RC522

STM32模拟SPI总线读写RFID模块RC522 RC522是一款NXP 公司的支持ISO14443A协议的高频(13.56MHz)RFID射频芯片。RFID有ID和IC两种卡应用类型,RC522属于IC卡的应用类型。NFC则属于增强的IC卡类型,支持双向通信和更多类型的协议。 I…

es官网翻译之Exploring Your Cluster

Exploring Your Cluster 探索你的集群 The rest api rest 风格的 api Now that we have our node (and cluster) up and running, the next step is to understand how to 现在 我们已经将我们自己的节点(和集群) 启动并运行着, 下一个步骤是知道如何 communicate with it…

Java面试题每日10问(12)

1. What is String Pool? String pool is the space reserved in the heap memory that can be used to store the strings.The main advantage of using the String pool is whenever we create a string literal; the JVM checks the “string constant pool” first.If th…

速度为单GPU1.6倍,kaggle双GPU(ddp模式)加速pytorch攻略

accelerate 是huggingface开源的一个方便将pytorch模型迁移到 GPU/multi-GPUs/TPU/fp16 模式下训练的小巧工具。和标准的 pytorch 方法相比,使用accelerate 进行多GPU DDP模式/TPU/fp16 训练你的模型变得非常简单(只需要在标准的pytorch训练代码中改动不几行代码就可…

linux基功系列之man帮助命令实战

文章目录前言一、man命令介绍二、常用参数2.1 语法2.2 常用参数2.3 man页面的操作命令man命令使用案例1. 直接查看手册2. -aw 参数找到可以被查询的章节2.3 一次性查阅所有章节2.4 搜索手册页2.5 -L 设置查询语言总结前言 linux系统中的命令数量有上千的,即使是常用…

前端——周总结系列二

1 JS数组排序sort()方法 不传参数排序,默认根据Unicode排序 附录 传参数,使用比较函数,自己定义比较规则 简单数组排序 // 升序 function ascSort(a, b) {return a - b; } // 降序 function ascSort(a, b) {return b - a; }数组对象排序…

算法leetcode|31. 下一个排列(rust重拳出击)

文章目录31. 下一个排列:样例 1:样例 2:样例 3:提示:分析:题解:rustgoccpythonjava31. 下一个排列: 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0…

ROS2机器人编程简述humble-第二章-First Steps with ROS2 .1

ROS2机器人编程简述新书推荐-A Concise Introduction to Robot Programming with ROS2学习笔记流水账-推荐阅读原书。第二章主要就是一些ROS的基本概念,其实ROS1和ROS2的基本概念很多都是类似的。ROS2机器人个人教程博客汇总(2021共6套)如何更…

Linux chgrp 命令

Linux chgrp(英文全拼:change group)命令用于变更文件或目录的所属群组。与 chown 命令不同,chgrp 允许普通用户改变文件所属的组,只要该用户是该组的一员。在 UNIX 系统家族里,文件或目录权限的掌控以拥有…

(一)Jenkins部署、基础配置

目录 1、前言 1.1、Jenkins是什么 1.2、jenkins有什么用 2、 Jenkins安装 2.1、jdk安装 2.2、安装Jenkins 3、Jenkins配置 3.1、解锁Jenkins 3.2、插件安装 3.3、创建管理员 3.4、实例配置 4、汉化 4.1、下载Locale插件 4.2、设置为中文 5、设置中文失效解决步骤 1…

U-Boot 之零 源码文件、启动阶段(TPL、SPL)、FALCON、设备树

最近,工作重心要从裸机开发转移到嵌入式 Linux 系统开发,在之前的博文 Linux 之八 完整嵌入式 Linux 环境、(交叉)编译工具链、CPU 体系架构、嵌入式系统构建工具 中详细介绍了嵌入式 Linux 环境,接下来就是重点学习一…