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

news2024/9/28 21:21:04

文章目录

  • 引言
  • 抽象工厂模式简介
    • 定义与用途
    • 实现方式:
  • 使用场景
  • 优势与劣势
  • 抽象工厂模式在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";
    }

    @Override
    public String getBankName() {
        return BNAME;
    }
}

class ICICI implements Bank{

    private final String BNAME;

    ICICI(){
        BNAME="ICICI BANK";
    }

    @Override
    public String getBankName() {
        return BNAME;
    }
}

class SBI implements Bank{

    private final String BNAME;

    public SBI(){
        BNAME="SBI BANK";
    }

    @Override
    public 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. EMI

              rate=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 {

    @Override
    public void getInterestRate(double r){
        rate=r;
    }

}

//商业贷款
class BussinessLoan extends Loan{

    @Override
    public void getInterestRate(double r){
        rate=r;
    }

}

//教育贷款
class EducationLoan extends Loan{

    @Override
    public 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{

    @Override
    public 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;
    }

    @Override
    public Loan getLoan(String loan) {
        return null;
    }

}
public class LoanFactory extends AbstractFactory{

    @Override
    public Bank getBank(String bank){
        return null;
    }

    @Override
    public 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.coloradmin.cn/o/1262253.html

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

相关文章

QT linux下应用程序打包

一、应用程序app 1、应用程序的pro文件 2、 程序工作函数 3、app的UI界面 二、动态库lib 1、Lib类头文件 2、.cpp文件 三、对应用程序和动态库进行构建 1、对动态库进行qmake,然后进行构建 2、对应用程序进行qmake,然后进行构建 3、查看构建目录 四、编写脚本 …

零基础学编程轻松学编程,分享一款中文编程工具,编程构件简介

零基础学编程轻松学编程,分享一款中文编程工具,编程构件简介 中文编程开发语言工具编辑区界面截图如上图。 给大家分享一款中文编程工具 零基础轻松学编程,不需英语基础,编程工具可下载。 这款工具不但可以连接部分硬件&#…

Mac苹果视频剪辑:Final Cut Pro Mac

Final Cut Pro是一款由Apple公司开发的专业视频非线性编辑软件,是业界著名的视频剪辑软件之一。它最初发布于1999年,是Mac电脑上的一款独占软件。Final Cut Pro具有先进的剪辑工具、丰富的特效和颜色分级、音频处理等功能,使得用户可以轻松地…

Java后端开发——MVC商品管理程序

Java后端开发——MVC商品管理程序 本篇文章内容主要有下面几个部分: MVC架构介绍项目环境搭建商品管理模块Servlet代码重构BaseServlet文件上传 MVC 是模型-视图-控制器(Model-View-Controller),它是一种设计模式,也…

打破限制!MySQL 5.7至8.0跨版本迁移,1分钟搞定多版本数据迁移

在上个月,MySQL 5.7 正式结束了生命周期,即EOL(End of Life),意味着Oracle将不再为 MySQL 5.7 提供技术支持,包括Bug修复或安全漏洞,大大增加了使用数据库的风险。在全球关系型数据库市场中&…

WinMerge使用教程,WinMerge下载

一、下载 官方下载 WinMerge - You will see the difference… 官方地址:https://winmerge.org/ 阿里云盘下载 文件内容对比工具WinMerge2.16.25.25 https://www.alipan.com/s/r7MzudB235x 点击链接保存,或者复制本段内容,打开「阿里云盘…

Webpack——Webpack简介

1、什么是Webpack? Webpack是一个开源的JavaScript模块打包工具,其最核心的功能是解决模块之间的依赖,把各个模块按照特定的规则和顺序组织在一起,最终合并为一个JS文件(有时会有多个,这里讨论的只是最基本…

【Cisco Packet Tracer】构造超网

​​🌈个人主页:Sarapines Programmer🔥 系列专栏:《Cisco Packet Tracer | 奇遇记》⏰寄 语:风翻云浪激,剑舞星河寂。 临风豪情壮志在,拨云见日昂首立。 目录 ⛳️1. Cisco Packet Trace…

【JavaEE初阶】 HTTP协议和使用Fiddler抓包

文章目录 🎍HTTP协议是什么?🍀应用层协议(HTTP)存在的意义🎄HTTP 协议的工作过程🌴HTTP 协议格式🌳Fiddler抓包工具的使用🚩如何抓HTTPS的包? 🎋抓…

影刀实例二,小某书如何持续下载图片

一,案例背景: 小某书平台,利用影刀rpa搜索关键词,然后下载对应文章的图片. 二,思路 1. 登录小某书平台,将网页放大最大【手动完成,作为初始状态】 2. 利用影刀命令【打开输入对话框】获得要搜索…

如何解决中小制造业企业信息化难题?

中小企的信息化,难! 一、中小制造业企业信息化困难的原因主要有以下几点: 资金限制:中小制造业企业相对于大型企业来说资金有限,无法投入大量资金进行信息化建设。技术水平不足:中小制造业企业缺乏专业的…

分享一款4G低功耗摄像头接入物联网平台解决方案

首先介绍硬件方案: 应用场景-4G低功耗摄像头 该方案中,Module为G8100B(4G模块),HOST为海思摄像头(Linux or LiteOS),G8100B的USB可以在Host端虚拟出串口和网卡,G8100B符合以下条件进入休眠&…

基于单片机的大棚温湿度检测系统(论文+源码)

1. 系统设计 本课题主要开发一个大棚温湿度检测系统、其功能要求如下: 1.实现大棚温室环境的空气中的温湿度检测; 2.当检测到的土壤湿度低于阈值时,模拟水泵进行浇水,湿度太高则进行干燥; 4. 当检测到环境的温度太…

从零开始搭建博客网站-----构建项目

构建项目 视频参考链接 构建一个项目文件(node为17.16.0版本) 构建的过程中可能会出现一个选项,选择vueJavaScript npm init vitelatest easyblog-front-admin安装相关依赖 cd easyblog-front-admin npm install3. 运行 npm run dev好了…

反转链表的三种写法

题目链接:https://leetcode.cn/problems/reverse-linked-list/ 方法一:循环,维护好两个节点一个前一个后 class Solution {public ListNode reverseList(ListNode head) {ListNode pre null;ListNode local head;while(local ! null){List…

GUI加分游戏

需求目标 这个简单的游戏窗口包含一个得分标签和一个按钮。每次点击按钮时,得分增加1,并更新得分标签的显示。 效果 源码 /*** author lwh* date 2023/11/28* description 这个简单的游戏窗口包含一个得分标签和一个按钮。每次点击按钮时,…

python爱心代码高级

在Python中,我们可以使用matplotlib库来创建一个更高级的爱心图形。以下是一个示例: import matplotlib.pyplot as pltimport numpy as npx np.linspace(-2, 2, 1000)y1 np.sqrt(1-(abs(x)-1)**2)y2 -3*np.sqrt(1-(abs(x)/2)**0.5)fig, ax plt.subp…

Docker Swarm总结+service创建和部署、overlay网络以及Raft算法(2/5)

博主介绍:Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 🍅文末获取源码下载地址🍅 👇🏻 精彩专栏推荐订阅👇🏻…

CentOS 系列:CentOS 7文件系统的组成

CentOS 7文件系统的组成 文件系统的组成Linux的一些重要目录文件和目录名主机名文件权限绝对路径和相对路径绝对路径相对路径 文件系统的组成 一切从根开始 文件路径中只有第一个/是根目录,后面的/是分隔符 文件名区分大小写 除斜线(/)以外,其他的字符…

基于HTML+CSS+JavaScript的登录注册界面设计

一、界面效果: 二、HTML代码: 登录注册html: 登录成功html: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <h1>登录成功!</h1> </body> <…