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.hqwc.cn/news/224913.html

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

相关文章

Linux驱动开发笔记(五):驱动连接用户层与内核层的文件操作集原理和Demo

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134561660 红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

1146:吃糖果(C语言)

题目描述 HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢连续两次吃一样的糖果,喜欢先吃一颗A种类的糖果,下一次换一种口味,吃一颗B种类的糖果,这样&…

开始使用Spring Boot Admin吧-使用Nacos注册SBA

什么是 Spring Boot Admin(SBA)? Spring Boot Admin 是 codecentric 公司开发的一款开源社区项目,目标是让用户更方便的管理以及监控 Spring Boot 应用。 应用可以通过我们的Spring Boot Admin客户端(通过HTTP的方式&#xff0…

技术人如何实现颠覆式成长

前言 颠覆式成长要求个人不断创新、承担风险,并抓住机遇。通过创新的方法,充分发挥个人的优势,并在个人成长中突破传统、发挥独特的方式和思考,从而实现个人创造力和效能的突破。 颠覆式成长需要不断学习和个人发展,…

C#:程序发布的大小控制

.net不讨喜有个大原因就是.net平台本身太大了,不同版本没有兼容性,程序依赖哪个版本用户就要安装哪个版本,除非你恰好用的是操作系统默认安装的版本——问题是不同版本操作系统默认安装的不一样。 所以打包程序就很头疼,不打包平台…

VScode集成python开发环境和基本插件下载配置

VSCode开发工具 下载VSCode VSCode官方首页:Visual Studio Code - Code Editing. Redefined 点击Download for Windows下载 安装过程一路下一步即可,其中建议勾选 将"通过Code打开"操作添加到Windows资源管理器目录上下文菜单方便我们直接通过…

【电路笔记】-电阻器颜色代码与阻值计算

电阻器颜色代码与阻值计算 文章目录 电阻器颜色代码与阻值计算1、概述2、计算电阻器颜色代码值3、贴片电阻器 电阻器颜色编码使用色带轻松识别电阻器的电阻值及其百分比容差。 1、概述 由于有许多不同类型的电阻器可用,我们需要形成电阻器颜色代码系统以便能够识别…

视频字幕处理+AI绘画,Runway 全功能超详细使用教程(4)

runway的视频字幕处理、AI绘图功能介绍,感觉完全就是为了做电影而布局,一整套功能都上线了!想系统学习的必收藏! 在深度研究Runway各个功能后,无论是AI视频生成及后期处理技术,还是AI图像生成技术&#xff…

手把手教会你--渗透实战--最开始的靶机演示--项目二:Lampiao

有什么问题,请尽情问博主,QQ群796141573 前言。。。知识1.1 开头介绍1.2 22/80端口1.3 nmap1.4 IP地址1.5 开启靶机--网络模式1.6 信息收集(1) 查看源代码(2) 查看常见漏洞(3) 随便点一点\改一改 1.7 robots.txt。。。实战1.1 确定目标(1) 查看自己的ip地…

从裸机启动开始运行一个C++程序(十五)

前序文章请看: 从裸机启动开始运行一个C程序(十四) 从裸机启动开始运行一个C程序(十三) 从裸机启动开始运行一个C程序(十二) 从裸机启动开始运行一个C程序(十一) 从裸机启…

动态规划专项---状态机模型

文章目录 大盗阿福股票买卖IV股票买卖V设计密码修复DNA 一、大盗阿福OJ链接 本题思路:状态表示当前第i家店铺选择偷或者不偷的最大利益。状态计算:f[i][0]std::max(f[i-1][0],f[i-1][1]);//如果第i家店铺被偷,则第i-1家店铺不能被偷,f[i][1]f[i-1][0]w[i]…

如何实现经济破圈?跟随“绿色积分”先行一步!

近年来,随着消费升级和信息技术的发展,新型消费逐渐成为推动经济增长的重要力量。为了加快发展新型消费,国家政府出台了一系列政策措施,《关于以新业态新模式引流新型消费加快发展》文件就是其中之一。本文将从该文件的背景、目的…