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";
    }

    @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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索容灾架构演进之路,从单点到异地多活

1. 挑战与变革 在公司发展初期,业务发展和用户增长是首要关注的焦点。然而,随着业务规模不断扩大,用户数量逐渐攀升,应用稳定性的重要性也变得愈发凸显。在这个演进过程中,传统架构下的应用部署模式开始显露出多方面的…

多类场景、遍布各地,融云 IM 支撑多款应用全球增长

(全网都在找的《社交泛娱乐出海作战地图》,点击获取👆) 无论是面向企业场景的工作流协同还是消费场景的网络效应形成,商务社交还是陌生人社交,IM 都是必备组件。IM 遍布互联网各角落,出现在所有…

用于图像分类任务的经典神经网络综述

🎀个人主页: https://zhangxiaoshu.blog.csdn.net 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️,如有错误敬请指正! 💕未来很长,值得我们全力奔赴更美好的生活&…

C++标准模板库 STL 简介(standard template library)

在 C 语言中,很多东西都是由我们自己去实现的,例如自定义数组,线程文件操作,排序算法等等,有些复杂的东西实现不好很容易留下不易发现的 bug。而 C为使用者提供了一套标准模板库 STL,其中封装了很多实用的容器&#xf…

基于单片机设计的超声波测距仪(采用HC-SR04模块)

一、前言 本项目是基于单片机设计的超声波测距仪,主要采用了STC89C52单片机和HC-SR04超声波测距模块。通过LCD1602液晶显示屏来展示测量的距离信息。 超声波测距技术是一种常见的非接触式测距方法,利用超声波的传播速度测量物体与测距器之间的距离。它…

GDOUCTF2023-Reverse WP

文章目录 [GDOUCTF 2023]Check_Your_Luck[GDOUCTF 2023]Tea[GDOUCTF 2023]easy_pyc[GDOUCTF 2023]doublegame[GDOUCTF 2023]L!s![GDOUCTF 2023]润!附 [GDOUCTF 2023]Check_Your_Luck 根据 if 使用z3约束求解器。 EXP: from z3 i…

【C++】探索C++模板编程

文章目录 什么是C模板?模板的基本语法类型模板参数模板函数的示例类模板的示例总结 C模板是一种强大的编程工具,它可以实现泛型编程,使代码更加灵活和可重用。本篇博客将介绍C模板的基本语法、类型模板参数和模板函数的使用,并通过…

第20章:多线程

20.1 线程简介 在Java中,并发机制非常重要,程序员可以在程序中执行多个线程,每个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。但是,并不是所有编程语言都支持多线程。 线程的特点&#…

集群 CPU 利用率均值达 45% ,揭秘小红书规模化混部技术实践

根据 Gartner 预测数据显示:2024 年全球 IT 支出预计将达到 5.1 万亿美元,比 2023 年增长 8 %。然而,该机构的另一项调查数据显示:全球数据中心服务器平均 CPU 利用率普遍低于 20%,存在巨大的资源浪费。据测算&#xf…

Python内置函数与标准库函数的解释示例

一、内置函数与标准库函数的区分 Python 解释器自带的函数叫做内置函数,这些函数可以直接使用,不需要导入某个模块。 Python 解释器也是一个程序,它给用户提供了一些常用功能,并给它们起了独一无二的名字,这些常用功能…

C语言——标识符

一、标识符是什么 标识符是C程序的最基本组成部分,例如:变量名称、函数名称、数据类型等等,都是一个标识符。标识符的要求是:必须由字母(区分大小写)、数字、下划线组成。而且,标识符的第一个字…

Django回顾【一】

一、Web应用程序 Web应用程序是一种可以通过Web访问的应用程序&#xff0c;程序的最大好处是用户很容易访问应用程序&#xff0c;用户只需要有浏览器即可&#xff0c;不需要再安装其他软件。应用程序有两种模式C/S、B/S。 C/S&#xff1a;客户端<----->服务端 例如My…

共筑关基安全防线,开源网安加入中关村华安关键信息基础设施安全保护联盟

近日&#xff0c;开源网安正式加入“中关村华安关键信息基础设施安全保护联盟”&#xff08;以下简称&#xff1a;关保联盟&#xff09;成为会员单位&#xff0c;进一步加强与行业内重要机构、企业的协同合作&#xff0c;推动关键信息基础设施安全保护领域的生态建设。 未来&am…

9.Spring 整合 Redis

引入依赖&#xff1a;spring-boot-starter-data-redis配置 Redis&#xff1a;配置数据库参数、编写配置类&#xff0c;构造 RedisTemplate访问 Redis&#xff1a; redisTemplate.opsForValue() redisTemplate.opsForHash() redisTemplate.opsForList() redisTemplate.opsForSe…

Codebeamer—软件全生命周期管理轻量级平台

产品概述 Codebeamer涵盖了软件研发的生命周期&#xff0c;在一个整合的平台内支持需求管理、测试管理、软件开发过程管理以及项目管理等&#xff0c;同时具有IToperations&DevOps相关的内容&#xff0c;并支持变体管理的功能。对于使用集成的应用程序生命周期管理&#xf…

LVS-DR实验

实验前准备 DR服务器&#xff1a;192.168.188.11 192.168.188.15 NFS服务器&#xff1a;192.168.188.14 Web服务器1&#xff1a;192.168.188.12 Web服务器2&#xff1a;192.168.188.13 Vip&#xff1a;192.168.188.188 客户端&#xff1a;192.168.188.200 配置负载均衡调度…

Stable Video Diffusion重磅发布:基于稳定扩散模型的AI生成视频

最近&#xff0c;stability.ai发布了稳定视频扩散&#xff0c;这是stability.ai第一个基于图像模型稳定扩散的生成视频基础模型。现在可以在研究预览中看到&#xff0c;这个最先进的生成人工智能视频模型代表着stability.ai在为每种类型的人创建模型的过程中迈出了重要的一步。…

C++学习之路(七)C++ 实现简单的Qt界面(消息弹框、按钮点击事件监听)- 示例代码拆分讲解

这个示例创建了一个主窗口&#xff0c;其中包含两个按钮。第一个按钮点击时会显示一个简单的消息框&#xff0c;第二个按钮点击时会执行一个特定的操作&#xff08;在这个例子中&#xff0c;仅打印一条调试信息&#xff09;。 功能描述&#xff1a; 创建窗口和布局&#xff1a;…

linux 内核线程

内核线程类似于用户进程&#xff0c;通常用于并发处理些工作&#xff0c;它是一种在内核空间实现后台任务的方式&#xff0c;并且可以参与时间片轮转调度。 内核线程可以进行繁忙的异步事件处理&#xff0c;也可以睡眠等待某事件的发生&#xff0c;内核线程可以访问内核函数和…

名词解释之EID和SR

大家在聊辅助驾驶时&#xff0c;经常会发现有名词叫SR&#xff0c;或者EID&#xff0c;理想的环境感知界面叫EID&#xff0c;而其他很多车型里大家管那个界面叫SR。我们下面具体看下这两个词具体指什么。 SR是“Situational Awareness”的缩写,意思是环境感知或场景认知。 SR系…