java设计模式学习之【抽象工厂模式】

文章目录

  • 引言
  • 抽象工厂模式简介
    • 定义与用途
    • 实现方式:
  • 使用场景
  • 优势与劣势
  • 工厂模式在spring中的应用
  • 银行和贷款服务示例
  • 代码地址

引言

在我们之前的讨论中,我们探索了工厂方法模式——一种简化单一产品创建的设计模式。现在,我们将视角转向抽象工厂模式,这是一种更高层次的设计模式,用于管理和创建一系列相关的产品。

抽象工厂模式简介

定义与用途

抽象工厂模式是创建型设计模式的一个高级形式,它允许生成一系列相关或相互依赖的对象。与工厂方法模式相比,抽象工厂模式在创建多种相关产品时提供了更大的灵活性和扩展性。

实现方式:

通过定义一个中心化的工厂类接口来创建一组相关或相互依赖的对象,而具体的创建逻辑由实现该接口的具体工厂类完成。

使用场景

  • 管理相关对象的家族:当需要创建一组执行相似功能但具有不同变体的对象时,例如不同类型的用户界面组件。
  • 系统配置对客户端透明:当客户端不需要知道它使用的具体实现细节,只关心接口时。
  • 动态切换产品系列:在运行时切换不同的实现(如不同的数据库平台或操作系统环境)而不影响客户端代码。
  • 强调平台独立性和一致性:当系统需要在不同的环境中提供一致的操作,并保持与平台的独立性时。

优势与劣势

  • 优势
    提高了系统的抽象性和可维护性:客户端代码只与抽象工厂和产品接口交互,提高了系统的灵活性。
    增强了系统的扩展性:可以轻松添加新的产品族,而无需修改现有代码。
  • 劣势
    增加了系统的复杂性:由于引入了多个接口和类。
    扩展新种类的产品难度较高:添加新产品需要修改抽象工厂接口。

工厂模式在spring中的应用

  • Spring中的BeanFactory和它的扩展ApplicationContext是抽象工厂模式的经典应用。它们提供了一个高级的工厂接口来创建应用中的对象和服务。
  • ApplicationContext通过读取配置文件来创建和管理bean,而这些bean可以被视为产品,Spring容器(工厂)管理着它们的整个生命周期。
  • FactoryBean 接口:Spring中的FactoryBean接口是抽象工厂模式的另一个应用。实现了FactoryBean的类负责产生其他bean的实例。
    这允许实现复杂的初始化逻辑,或者返回一个与实现类逻辑不同的对象实例。

银行和贷款服务示例

  • 我们将创建一个银行接口(Bank interface)和一个贷款抽象类(Loan abstract class)以及它们的子类。
  • 接着,我们将创建一个抽象工厂类(AbstractFactory class)
    我们将创建具体的类,银行工厂(BankFactory)和贷款工厂(LoanFactory),这些类将继承抽象工厂类。
  • 抽象工厂模式示例类(AbstractFactoryPatternExample class)使用工厂创造器(FactoryCreator)来获取抽象工厂类的对象。

在这里插入图片描述
步骤 1: 创建银行接口

public interface Bank {String getBankName();
}

步骤 2: 实现银行接口的具体类

class HDFC implements Bank{private final String BNAME;public HDFC(){BNAME="HDFC BANK";}@Overridepublic String getBankName() {return BNAME;}
}class ICICI implements Bank{private final String BNAME;ICICI(){BNAME="ICICI BANK";}@Overridepublic String getBankName() {return BNAME;}
}class SBI implements Bank{private final String BNAME;public SBI(){BNAME="SBI BANK";}@Overridepublic String getBankName(){return BNAME;}
}

步骤 3: 创建贷款抽象类

public abstract class Loan {protected double rate;abstract void getInterestRate(double rate);public void calculateLoanPayment(double loanamount, int years){/*to calculate the monthly loan payment i.e. EMIrate=annual interest rate/12*100;n=number of monthly installments;1year=12 months.so, n=years*12;*/double EMI;int n;n=years*12;rate=rate/1200;EMI=((rate*Math.pow((1+rate),n))/((Math.pow((1+rate),n))-1))*loanamount;System.out.println("每月等额还款:"+ EMI +" 贷款总额:"+loanamount+"");}}

步骤 4: 继承贷款抽象类的具体类

//家庭贷款
class HomeLoan extends Loan {@Overridepublic void getInterestRate(double r){rate=r;}}//商业贷款
class BussinessLoan extends Loan{@Overridepublic void getInterestRate(double r){rate=r;}}//教育贷款
class EducationLoan extends Loan{@Overridepublic void getInterestRate(double r){rate=r;}}

步骤 5: 创建抽象工厂类

public abstract class AbstractFactory {public abstract Bank getBank(String bank);public abstract Loan getLoan(String loan);}

步骤 6: 创建继承AbstractFactory类的工厂类,根据给定的信息生成具体类的对象。

public class BankFactory extends AbstractFactory{@Overridepublic Bank getBank(String bank){if(bank == null){return null;}if(bank.equalsIgnoreCase("HDFC")){return new HDFC();} else if(bank.equalsIgnoreCase("ICICI")){return new ICICI();} else if(bank.equalsIgnoreCase("SBI")){return new SBI();}return null;}@Overridepublic Loan getLoan(String loan) {return null;}}
public class LoanFactory extends AbstractFactory{@Overridepublic Bank getBank(String bank){return null;}@Overridepublic Loan getLoan(String loan){if(loan == null){return null;}if(loan.equalsIgnoreCase("Home")){return new HomeLoan();} else if(loan.equalsIgnoreCase("Business")){return new BussinessLoan();} else if(loan.equalsIgnoreCase("Education")){return new EducationLoan();}return null;}}

**步骤 7:**创建一个FactoryCreator类,通过传递Bank或Loan之类的信息来获取工厂。

public class FactoryCreator {public static AbstractFactory getFactory(String choice){if(choice.equalsIgnoreCase("Bank")){return new BankFactory();} else if(choice.equalsIgnoreCase("Loan")){return new LoanFactory();}return null;}}

**步骤 8:**使用FactoryCreator获取AbstractFactory,以便通过传递类型等信息来获取具体类的工厂。

public class AbstractFactoryPatternExample {public static void main(String args[]) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("输入你想贷款银行的名称: ");String bankName = br.readLine();System.out.print("\n");System.out.print("输入你想贷款的类型: ");String loanName = br.readLine();AbstractFactory bankFactory = FactoryCreator.getFactory("Bank");Bank b = bankFactory.getBank(bankName);System.out.print("\n");System.out.print("输入利率 " + b.getBankName() + ": ");double rate = Double.parseDouble(br.readLine());System.out.print("\n");System.out.print("输入贷款金额: ");double loanAmount = Double.parseDouble(br.readLine());System.out.print("\n");System.out.print("输入贷款年限: ");int years = Integer.parseInt(br.readLine());System.out.print("\n");System.out.println("你正在从银行贷款 " + b.getBankName());AbstractFactory loanFactory = FactoryCreator.getFactory("Loan");Loan l = loanFactory.getLoan(loanName);l.getInterestRate(rate);l.calculateLoanPayment(loanAmount, years);}}

以上就是一个简单的抽象工厂示例代码,运行代码我们可以看到:
输入相应的数据就可以算出不同银行,不同贷款类型下具体贷款明细了。
在这里插入图片描述

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

2023年亚太杯APMCM数学建模大赛A题水果采摘机器人的图像识别

2023年亚太杯APMCM数学建模大赛 A题 水果采摘机器人的图像识别 原题再现 中国是世界上最大的苹果生产国,年产量约3500万吨。同时,中国也是世界上最大的苹果出口国,世界上每两个苹果中就有一个是中国出口的,世界上超过六分之一的…

VMware系列:VMware16安装Win11虚拟机(最全步骤+踩坑)

VMware16安装Win11虚拟机(最全步骤+踩坑) 以下是安装步骤和踩坑大全准备工作下载镜像安装/配置的流程1、检查安装的系统环境是否符合最低要求2. 这里给出需要注意的几个点3. 如果出现了如下情况、请看下面的【三】安装Windows11出现问题解决!!!!4. 注意:如果没有出现【驱…

Star History 十月开源精选 |AI for Postgres

在 2023 年 Stack Overflow 开发者调查中,Postgres 顶替了 MySQL 被评为最受欢迎的数据库。一个重要因素应该是 Postgres 支持扩展:可扩展的架构 Postgres 仍然由社区拥有,Postgres 生态近年来蓬勃发展。 扩展可以看作是内置功能&#xff0c…

自定义的AlphaShape类来提取平面点云数据的边界点 open3d c++ 代码 平面点云边界提取算法

使用了自定义的AlphaShape类来提取点云数据的边界点,并使用Open3D库进行可视化。 引入必要的头文件和命名空间: main函数: 读取点云数据文件到cloud对象。如果读取失败,则输出错误信息并返回。将点云数据全部着色为蓝色。创建一个空的点云对象boundaryCloud,用于存储提取…

跟着chatgpt学习|1.spark入门

首先先让chatgpt帮我规划学习路径,使用Markdown格式返回,并转成思维导图的形式 目录 目录 1. 了解spark 1.1 Spark的概念 1.2 Spark的架构 1.3 Spark的基本功能 2.spark中的数据抽象和操作方式 2.1.RDD(弹性分布式数据集) 2…

9:kotlin 返回和跳过(Returns and jumps)

kotlin有三种结构跳转表达式: return会从最近的封闭函数或匿名函数返回。 break终止最近的封闭循环。 continue继续最近的封闭循环的下一步。 所有这些表达式都可以作为其他表达式的一本分使用 val s person.name ?: returnval s person.name ?: return 这…

SpringBoot yml配置文件打印值

目录 SpringBoot中配置文件打印值 yml配置 config类 启动类 测试类 注解分析 SpringBoot中配置文件打印值 yml配置 student:red: douconfig类 Data ConfigurationProperties(prefix "student") // 文件上传 配置前缀file.oss public class MinIOConfigProp…

Callable、Future和FutrueTask详解

一、Callable介绍 1.1 Runnable介绍 Runnable是一个接口,里面声明了run方法。但是由于run方法返回值类型为void,所以在执行完成任务后,无法返回任何结果。 FunctionalInterface public interface Runnable {public abstract void run(); }…

仅2万粉,带了2.6万件的货!TikTok Shop美区达人周榜(11.13-11.19)

11月24日,TikTok Shop近日公布了美国市场和英国市场的全托管黑五大促战绩。数据显示,11月14日至11月20日,其美国市场的订单量环比10月20日-10月26日增长了205%。 家居户外热销品有:数码触摸屏相框、毛绒地毯、家居毛毯。黑马商品…

关于微信小程序中如何实现数据可视化-echarts动态渲染

移动端设备中,难免会涉及到数据的可视化展示、数据统计等等,本篇主要讲解原生微信小程序中嵌入echarts并进行动态渲染,实现数据可视化功能。 基础使用 首先在GitHub上下载echarts包 地址:https://github.com/ecomfe/echarts-for…

SD-WAN和混合WAN两种网络方案的差异

传统的WAN是指基于传输控制协议/因特网协议(TCP/IP)的私有广域网(WAN),它由企业网络和ISP组成,用于连接分布在不同地理位置的多个站点。使用传统WAN时,企业需要租用电路,使用专用线路…

机器学习-线性模型·

线性模型是一类用于建模输入特征与输出之间线性关系的统计模型。这类模型的基本形式可以表示为: 其中: 是模型的输出(目标变量)。 是截距(常数项,表示在所有输入特征都为零时的输出值)。 是权重…

2311skia,08解码区域

解码区域 1,抽象 1,图片很大时,解码速度缓慢,占用内存很高,并且,图片超过一定尺寸时,无法上传和显示纹理(这跟GPU能力有关,一般的GPU是8192*8192).这时只好下采样,但会牺牲图片显示质量. 2,-对图库等,需要清晰浏览图片的应用,不可能设置下采样率来解决这一问题,因此,Google加…

The Matrix format of Least Square Method (LMS)

I. Cost function For the cost function J ∑ i 1 n ∣ ∣ y i − x i T θ ∣ ∣ 2 (1) J \sum_{i1}^n || y_i - x_i^T \theta ||^2 \tag{1} Ji1∑n​∣∣yi​−xiT​θ∣∣2(1) where θ ( m 1 ) \theta (m\times 1) θ(m1) is the unknow parameters, x i T ( 1 m…

基于官方YOLOv4-u5【yolov5风格实现】开发构建目标检测模型超详细实战教程【以自建缺陷检测数据集为例】

本文是关于基于YOLOv4开发构建目标检测模型的超详细实战教程,超详细实战教程相关的博文在前文有相应的系列,感兴趣的话可以自行移步阅读即可: 《基于yolov7开发实践实例分割模型超详细教程》《YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程》《DETR (DE…

内衣洗衣机怎么选?内衣洗衣机便宜好用的牌子推荐

相信不少用户并不太在意衣服和内衣裤裤能不能同时洗,每次清洗都是把内衣裤与其他衣服一起放入洗衣机清洗,其实内衣裤不能直接跟大件的衣物一起放入洗衣机洗的,很容易会造成我们皮肤的瘙痒,我们大部分时间都在户外,暴露…

python 基于opencv和face_recognition的人脸识别

python 基于opencv和face_recognition的人脸识别 代码如下: 使用一个photos存放你需要识别的照片,注意一个人一张就行 然后通过下面代码注册用户,之后启动程序,就会调用摄像头进行识别了。 AddPhoto(“发哥”, “./photos/fag…

Java实现集合和Excel文件相互转换

目录 一、集合转化为Excel文件二、Excel文件转化为集合 一、集合转化为Excel文件 效果如下,是将集合转化为Excel文件,Excel包含合并单元格。 实体类: Data public class ClassGrade {/** 年级 */private String grade;/** 班主任 */privat…

纯新手发布鸿蒙的第一个java应用

第一个java开发鸿蒙应用 1.下载和安装华为自己的app开发软件DevEco Studio HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 2.打开IDE新建工程(当前用的IDEA 3.1.1 Release) 选择第一个,其他的默认只能用(API9)版本,…

ConcurrentHashMap的数据结构+以及各个版本之间的区别

ConcurrentHashMap 1.7与1.8的区别 1、锁结构不同 2、put的流程不同 3、size的计算方式不同(1.8使用的使用basecell[]计算,有点类似于LongAdder,1.7使用三级通缉判断是否一样,不一样通过分段式加锁再求和) 4、数据结构不同,1.6 Re…