【设计模式深度剖析】【2】【创建型】【工厂方法模式】

👈️上一篇:单例模式    |   下一篇:抽象工厂模式👉️

目录

  • 工厂方法模式
    • 概览
    • 工厂方法模式的定义
      • 英文原话
      • 直译
    • 工厂方法模式的4个角色
      • 抽象工厂(Creator)角色
      • 具体工厂(Concrete Creator)角色
      • 抽象产品(Product)角色
      • 具体产品(Concrete Product)角色
      • 类图
      • 代码示例
        • 抽象工厂Creator.java
        • 具体工厂ConcreteCreator.java
        • 抽象产品Product.java
        • 具体产品ConcreteProduct.java
        • 应用代码ClientFactoryMethodDemo.java
    • 工厂方法模式的应用
      • 工厂方法模式的优点
      • 工厂方法模式的使用场景
    • 工厂方法模式的示例解析
      • 类图
      • 1. 抽象工厂类:FruitGardener.java(果子园接口,生产各类水果的)
      • 2. 具体工厂类:
        • 2.1 具体的某果园:AppleGardener.java (苹果园类,生产苹果)
        • 2.2 具体的某果园:GrapeGardener.java(葡萄园类,生产葡萄)
      • 3. 抽象产品类:Fruit.java(水果接口,抽象的水果类)
      • 4. 具体产品类:
        • 4.1 具体的某类水果:Apple.java(苹果类,是一种具体的水果)
        • 4.2 具体的某类水果:Grape.java(葡萄类,是一种具体的水果)
      • 5. 测试类

工厂方法模式

工厂方法模式(Factory Method Pattern)又叫虚拟构造函数(Virtual Constructor)模式
或者多态性工厂(PolymorphicFactory)模式
。工厂方法模式的用意是定义一个创建产品对象
的工厂接口,将实际创建性工作推迟到子类中

工厂模式可分为简单工厂、工厂方法和抽象工厂模式。

  • 简单工厂模式中一个工厂类处于对产品类实例化的中心位置上,它知道每一个产品,它决定哪一个产品类应当被实例化

这个模式的优点是允许客户端相对独立于产品创建的过程,并且在系统引入新产品的时候无须修改客户端,即在某种程度上支持“开-闭”原则(一个软件实体应当对扩展开放,对修改关闭)。
这个模式的缺点是对 “开-闭” 原则的支持不够,因为如果有新的产品加入到系统中,则需要修改工厂类,将必要的逻辑加入到工厂类中。

  • 工厂方法模式简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,且克服了它的缺点。

首先,在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做。这个核心类则成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪个产品类应当被实例化的细节。此种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品,这一特点使得工厂模式具有超过简单工厂的优越性。

  • 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态

    抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构

概览

  • 工厂方法模式的定义

  • 工厂方法模式的4个角色

  • 工厂方法模式的应用

    • 工厂方法模式的优点
    • 工厂方法模式的使用场景
  • 工厂方法模式的示例解析

  • 待办:工厂方法模式的使用场景 第三条/第四条

工厂方法模式的定义

英文原话

Define an interface for creating an object, but let subclasses decide which class to instantiate. FactoryMethod lets a class defer instantiation to subclasses.

直译

意思是:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

工厂方法模式的4个角色

抽象工厂(Creator)角色

该角色是工厂方法模式的核心,与应用系统无关,任何在创建对象的工厂类必须实现这个接口。

具体工厂(Concrete Creator)角色

该角色实现了抽象工厂接口,含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。

抽象产品(Product)角色

该角色负责定义产品的共性,实现对产品最抽象的定义。

具体产品(Concrete Product)角色

该角色实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。

类图

工厂方法模式类图

代码示例

示例代码

抽象工厂Creator.java
public interface Creator {//工厂方法//创建一个产品对象,其输入参数类型可自行设置public <T extends Product> T factory(Class<T> c);
}
具体工厂ConcreteCreator.java
public class ConcreteCreator implements Creator {@Overridepublic <T extends Product> T factory(Class<T> c) {Product product = null;try {product= (Product) Class.forName(c.getName()).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return (T) product;}
}
抽象产品Product.java
public interface Product {//产品类的公共方法public void method1();public void method2();
}
具体产品ConcreteProduct.java
public class ConcreteProduct implements Product {@Overridepublic void method1() {//业务逻辑处理代码System.out.println("test method1()");}@Overridepublic void method2() {//业务逻辑处理代码}
}
应用代码ClientFactoryMethodDemo.java
public class ClientFactoryMethodDemo {public static void main(String[] args) {Creator creator = new ConcreteCreator();Product product = creator.factory(ConcreteProduct.class);//继续业务处理product.method1();}
}

[注]:上述通用代码是一个比较实用的、易扩展的框架,可以根据实际项目需要进行扩展应用。

工厂方法模式的应用

工厂方法模式的优点

  1. 良好的封装性,代码结构清晰。一个对象创建是有条件约束的,如果一个调用者需要一个具体的产品对象
    只要知道这个产品的类名或约束字符串即可,不用知道创建对象的过程如何,降低了模块间的耦合。
  2. 优秀的可扩展性在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以适应变化
  3. 屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,而只需要关心产品的接口,只要接口保持不变,
    系统的上层模块就不需要发生变化
    。因为产品的实例化是由工厂类负责的,具体生产何种产品对象是由不同的工厂类
    决定的。
  4. 工厂方法模式是典型的解耦框架高层模块只需要知道产品的抽象类,其他的实现类都不用关心。
    工厂方法模式符合迪米特法则 (又叫最少知识原则(Least Knowledge Principle,LKP).
    只与你直接的朋友们通信(Only talk to your immediatefriends);
    不要跟“陌生人”说话(Don’t talk to strangers);),也符合依赖倒置原则
    (高层模块不应该依赖低层模块,两者都依赖其抽象;抽象不依赖细节 细节应该依赖于抽象。),只依赖产品类的抽象;
    另外还符合里氏替换原则,可以使用产品子类替换产品父类。

工厂方法模式的使用场景

工厂方法模式在项目中使用得非常频繁,在很多框架的代码中都可以发现工厂方法模式的应用。可使用工厂方法模式的典型场景如下。

  • 工厂方法模式是new一个对象的替代品,因此在所有需要生成对象的地方都可以使用,
    但是需要慎重考虑是否需要增加一个工厂类进行管理,增加代码的复杂度。
  • 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
  • 工厂方法模式可以用在异构项目中,例如,通过WebService与一个非Java的项目交互,虽然WebService号称是可以做到异构系统的同构化,但是在实际开发中,还是会碰到很多问题,如类型问题、WSDL文件的支持问题等。从WSDL中产生的对象都认为是一个产品,然后由一个具体的工厂类进行管理,减少与外围的耦合。
  • 工厂方法模式可以使用在测试驱动开发的框架下。例如,测试一个类 A,就需要将与类A关联的类B也同时产生出来,使用工厂方法模式可以将类B虚拟出来,避免类A与类B的耦合。
  • [注]工厂方法模式还可以与其他模式混合使用(如模板方法模式、单例模式、原型模式等),从而构造出扩展性更好的设计。

工厂方法模式的示例解析

代码示例

通过农场系统演示工厂方法模式的应用(但是工厂方法模式只能针对一个产品等级结构如A产品B产品。但是如果是A产品与B产品的第一等级第二等级,这种情况要抽象工厂模式。)

类图

FuitProductFactory.png

1. 抽象工厂类:FruitGardener.java(果子园接口,生产各类水果的)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果园丁FruitGardener接口是抽象工厂** @author Polaris 2024/5/16*/
public interface FruitGardener {Fruit factory();
}

2. 具体工厂类:

2.1 具体的某果园:AppleGardener.java (苹果园类,生产苹果)

该具体工厂-苹果园工厂,封装了实例化具体产品-苹果对象的过程

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 苹果园丁AppleGardener实现FruitGardener接口,是一个用于生产苹果的具体工厂** @author Polaris 2024/5/16*/
public class AppleGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Apple();}
}
2.2 具体的某果园:GrapeGardener.java(葡萄园类,生产葡萄)

该具体工厂-葡萄园工厂,封装了实例化具体产品-葡萄对象的过程

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄园丁GrapeGardener实现FruitGardener接口,是一个用于生产葡萄的具体工厂** @author Polaris 2024/5/16*/
public class GrapeGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Grape();}
}

3. 抽象产品类:Fruit.java(水果接口,抽象的水果类)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果Fruit接口是抽象产品** @author Polaris 2024/5/16*/
public interface Fruit {//生长void grow();//收获void harvest();//栽种void plant();
}

4. 具体产品类:

4.1 具体的某类水果:Apple.java(苹果类,是一种具体的水果)

由于苹果是一类具体的水果类,因此它对抽象的水果类进行了实现,当然同时它也有独自属于它自己的方法。

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 苹果Apple实现Fruit接口,是一个具体产品** @author Polaris 2024/5/16*/
public class Apple implements Fruit {private int treeAge;public int getTreeAge() {return treeAge;}public void setTreeAge(int treeAge) {this.treeAge = treeAge;}@Overridepublic void grow() {System.out.println("苹果树在生长");}@Overridepublic void harvest() {System.out.println("收获苹果");}@Overridepublic void plant() {System.out.println("栽种苹果");}
}
4.2 具体的某类水果:Grape.java(葡萄类,是一种具体的水果)

由于葡萄是一类具体的水果类,因此它对抽象的水果类进行了实现,当然同时它也有独自属于它自己的方法。

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄Grape实现Fruit接口,是一个具体产品** @author Polaris 2024/5/16*/
public class Grape implements Fruit {private boolean seedless;public boolean isSeedless(){return seedless;}public void setSeedless(boolean seedless){this.seedless=seedless;}@Overridepublic void grow() {System.out.println("葡萄正在生长...");}@Overridepublic void harvest() {System.out.println("收获葡萄");}@Overridepublic void plant() {System.out.println("栽种葡萄");}
}

5. 测试类

具体某类水果工厂来生产对应的某水果对象,

该水果对象是某具体水果类的实例,

而该具体水果实例实现了抽象的水果类,

里氏替换原则,父类的引用可以指向子类实例,因为子类类型一定是父类类型(或者实现的接口的类型)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 下面是一个应用场景代码** @author Polaris 2024/5/16*/
public class ClientDemo {public static void main(String[] args) {//苹果园丁工厂FruitGardener fruitGardener = new AppleGardener();//通过工厂生产苹果Fruit apple = fruitGardener.factory();apple.plant();apple.grow();apple.harvest();fruitGardener = new GrapeGardener();//通过工厂生产葡萄Fruit grape = fruitGardener.factory();grape.plant();grape.grow();grape.harvest();}
}

👈️上一篇:单例模式    |   下一篇:抽象工厂模式👉️

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

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

相关文章

关于光照模型

关于光照模型 早期学习笔记&#xff0c;转载自早期Excel。 存在大量格式错误、可读性非常低&#xff0c;建议等待作者修复后阅读、或者作为查找性材料使用。 中文名英文名/缩写说明长什么样兰伯特光照模型Lambert Lighting1.兰伯特反射(Lambert)是最常见的一种漫反射&#x…

iptables防火墙【其二 实验篇】

保存&#xff0c;还原规则 防火墙规则的备份和还原 导出&#xff08;备份&#xff09;所有表的规则 iptables-save > /opt/ipt.txt 导入&#xff08;还原&#xff09;规则 iptables-restore < /opt/ipt.txt 将iptables规则文件保存在 /etc/sysconfig/iptables 中&#xf…

亚马逊卖家账号注册复杂吗?需要什么辅助工具吗?

在当今数字化的商业世界中&#xff0c;亚马逊作为全球最大的电商平台之一&#xff0c;吸引着无数的卖家和买家。对于想要进入亚马逊销售市场的卖家来说&#xff0c;首先要完成的一项重要任务就是注册亚马逊卖家账号。本文将详细介绍亚马逊注册的步骤、所需时间&#xff0c;以及…

LIMS系统能解决实验室管理的哪些痛点

LIMS&#xff08;Laboratory Information Management System&#xff0c;实验室信息管理系统&#xff09;在解决实验室管理的痛点方面发挥着重要作用。以下是LIMS系统能够解决的一些主要痛点&#xff1a; 一、人工介入大量重复性工作 LIMS系统能够自动化处理实验室中的许多重复…

[深度学习]基于yolov8+bytetrack+pyqt5实现车辆进出流量统计+车辆实时测速实现

以前使用过yolov5deepsort实现过车辆进出流量统计车辆实时测速&#xff0c;可以看我往期视频&#xff0c;这回改成yolov8bytetrack实现&#xff0c;实时性更好&#xff0c;原理和原来一样。车流量进出统计车速测量优点&#xff1a; 使用目标检测算法考虑bbox抖动&#xff0c;解…

C-数据结构-单向链表(带头节点)

单向链表带头节点&#xff08;head&#xff09;&#xff08;数据域&#xff0c;指针域&#xff09; 随机访问性比较差 但是插入删除操作较为简单。 list.h #ifndef LIST_H__ #define LIST_H__typedef int datatype;typedef struct node_st {datatype data;struct node_st *ne…

将富文本编辑器中的H标签处理成树形结构,支持无限层级

做富文本编辑器时&#xff0c;需要将文本里的标题整理成树形数据&#xff0c; // 这里是数据结构 const data [{"id": "hkyrq2ndc-36yttda0lme00","text": "阿萨德阿萨德阿萨","level": 1,"depth": 1,},{"…

Window Linux 权限提升

#基础点&#xff1a; 0、为什么我们要学习权限提升转移技术&#xff1a; 简单来说就是达到目的过程中需要用到它 心里要想着我是谁 我在哪 我要去哪里 1、具体有哪些权限需要我们了解掌握的&#xff1a; 后台权限&#xff0c;数据库权限&#xff0c;Web权限&#xff0c;用户权…

【VTKExamples::Texture】第六期 TextureThreshold

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例TextureThreshold,并解析接口vtkTexture,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~Y…

127.数据异构方案

文章目录 前言一、数据异构的常用方法1. 完整克隆2. MQ方式3. binlog方式 二、MQ与Binlog方案实现MQ方式binlog方式注意点 三、总结 前言 何谓数据异构&#xff1a;把数据按需&#xff08;数据结构、存取方式、存取形式&#xff09;异地构建存储。比如我们将DB里面的数据持久化…

Android 安全补丁介绍

Android 安全补丁介绍 每月安全补丁更新&#xff1a;https://source.android.com/docs/security/bulletin CEV 全称&#xff1a; Common Vulnerabilities and Exposures (CVE) 常见漏洞和暴露 (CVE) 安全补丁版本查看&#xff1a;设置&#xff0c;关于手机&#xff0c;Andro…

前端基础入门三大核心之HTML篇:无序列表的深度探索

前端基础入门三大核心之HTML篇&#xff1a;无序列表的深度探索 一、无序列表基础概念与作用1.1 什么是无序列表&#xff1f;1.2 无序列表的作用 二、基本用法与代码示例2.1 最简单的无序列表2.2 添加自定义样式 三、进阶应用与技巧3.1 列表嵌套3.2 利用CSS实现复杂布局3.3 安全…

云和恩墨海外首秀在吉隆坡召开的2024中国智能科技与文化展览会

作为中马建交50周年官方重点推荐的活动之一&#xff0c;2024中国智能科技与文化展览会&#xff08;第四届&#xff09;于5月20至21日在毗邻吉隆坡双子塔的吉隆坡国际会展中心举办。本次展览会获得马来西亚科学技术创新部、马来西亚通讯部、中国驻马来西亚大使馆和马来西亚中华总…

【Linux学习】进程地址空间与写时拷贝

文章目录 Linux进程内存布局图&#xff1a;内存布局的验证 进程地址空间写时拷贝 Linux进程内存布局图&#xff1a; 地址空间的范围&#xff0c;在32位机器上是2^32比特位,也就是[0,4G]。 内存布局的验证 代码验证内存布局&#xff1a; 验证代码&#xff1a; #include<s…

linux系统安全加固

目录 1、账户安全基本措施 1&#xff09;系统账户清理 2&#xff09;密码安全控制 3&#xff09;命令历史限制 2、用户切换及提权 1&#xff09;使用 su命令切换用户 2&#xff09;使用sudo机制提升权限 3、系统引导和安全登录控制 1&#xff09;开机安全控制 2&…

头歌实践教学平台:Junit实训入门篇

第2关&#xff1a;Junit注解 任务描述 给出一个带有注解的Junit代码及其代码打印输出&#xff0c;要求学员修改注解位置&#xff0c;让输出结果变为逆序。 相关知识 Junit注解 Java注解&#xff08;(Annotation&#xff09;的使用方法是" 注解名" 。借助注解&a…

python数据处理与分析入门-Pandas数据可视化例子

相关内容 Matplotlib可视化练习 Pandas 数据可视化总结 柱状图 reviews[points].value_counts().sort_index().plot.bar()散点图 reviews[reviews[price] < 100].sample(100).plot.scatter(xprice, ypoints)蜂窝图 reviews[reviews[price] < 100].plot.hexbin(xprice…

Helm安装kafka3.7.0无持久化(KRaft 模式集群)

文章目录 2.1 Chart包方式安装kafka集群 5.开始安装2.2 命令行方式安装kafka集群 搭建 Kafka-UI三、kafka集群测试3.1 方式一3.2 方式二 四、kafka集群扩容4.1 方式一4.2 方式二 五、kafka集群删除 参考文档 [Helm实践---安装kafka集群 - 知乎 (zhihu.com)](https://zhuanlan.…

virtualbox共享文件夹没有访问权限

设置好共享文件夹之后&#xff0c;进入虚拟机&#xff0c;共享文件夹的地址是/media/sf_shared。 想要使用cd命令进入该文件夹时&#xff0c;你可能会发现此文件夹无法访问&#xff0c;系统提示的原因是权限不足。 在虚拟机下查看共享文件夹的属性&#xff0c;发现该目录的所…

Nginx - 健康检查终极指南:探索Upstream Check模块

文章目录 概述upstream_check_module模块安装和配置指南模块安装步骤基本配置示例详细配置说明检查类型和参数常见问题及解决方案 SSL检查和DNS解析功能SSL检查配置示例和说明配置示例 DNS解析配置示例和说明配置示例 结合实际应用场景的高级配置示例综合SSL检查与DNS解析 总结…