当前位置: 首页 > article >正文

Java 工厂设计模式详解:用统一入口打造灵活可扩展的登录系统----掌握 Spring 源码的基础第一步

一、前言

在实际开发中,我们经常面临以下场景:

  • 系统支持多种登录方式(用户名密码、管理员登录、OAuth 登录、短信登录等)

  • 每种登录方式的认证逻辑不同

  • 我们希望对外提供一个统一的接口调用,而不暴露具体实现

这个时候,工厂设计模式(Factory Pattern)就是解决这种需求的最佳利器。

在本文中,我们通过一个模拟登录系统的实际案例,带你深入理解工厂模式的结构、优点和应用场景。

二、什么是工厂模式?

工厂模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类。这样,我们可以将对象的创建与使用解耦,实现更强的扩展性和可维护性。

通俗地说,工厂模式就像点外卖平台——你只管下单(告诉工厂你想吃什么),工厂帮你创建对应的“菜品实例”,你不需要关心这些菜是怎么做的。

三、代码结构总览

我们使用一个模拟登录系统的例子,分别支持:

  • 普通用户登录(用户名 + 密码)

  • 管理员登录

  • 第三方 OAuth 登录

结构如下:

com.Factory_Pattern
├── LoginService.java         // 抽象接口
├── UserLoginService.java     // 普通用户登录实现
├── AdminLoginService.java    // 管理员登录实现
├── OAuthLoginService.java    // OAuth 登录实现
├── LoginFactory.java         // 工厂类
└── Test.java                 // 测试入口

四、核心代码详解

1. 定义统一接口:LoginService

public interface LoginService {boolean login(String username, String credential);
}

所有登录服务都必须实现这个接口,保证调用方使用统一的方式调用。

2. 三种登录实现类

public class UserLoginService implements LoginService {@Overridepublic boolean login(String username, String password) {System.out.println("普通用户登录验证中...");return "user".equals(username) && "123".equals(password);}
}
public class AdminLoginService implements LoginService {@Overridepublic boolean login(String username, String password) {System.out.println("管理员登录验证中...");return "admin".equals(username) && "adminpass".equals(password);}
}
public class OAuthLoginService implements LoginService {@Overridepublic boolean login(String username, String token) {System.out.println("OAuth 登录验证中...");return "oauth_token".equals(token);}
}

每个实现类各自处理自己的登录逻辑,互不干扰,职责单一。

3. 工厂类 LoginFactory

public class LoginFactory {public static LoginService getLoginService(String userType) {switch (userType.toLowerCase()) {case "user":return new UserLoginService();case "admin":return new AdminLoginService();case "oauth":return new OAuthLoginService();default:throw new IllegalArgumentException("未知用户类型: " + userType);}}
}

这个工厂类根据 userType 动态创建不同的登录对象。调用方无需知道这些类的具体细节,只要提供一个标识即可。

4. 客户端使用(Test 类)

这个客户端代码从头到尾都没有出现任何具体子类的名字,只跟接口 LoginService 打交道,完美体现了解耦。

public class Test {public static void main(String[] args) {String userType = "oauth";String username = "admin";String token = "oauth_token";LoginService loginService = LoginFactory.getLoginService(userType);boolean success = loginService.login(username, token);System.out.println(success ? "登录成功!" : "登录失败!");}
}

这个客户端代码从头到尾都没有出现任何具体子类的名字,只跟接口 LoginService 打交道,完美体现了解耦。

五、工厂模式进阶建议

在实际项目中,工厂模式可以结合以下设计理念使用:

  • 策略模式:工厂只负责创建对象,具体逻辑交给策略执行

  • 配置驱动工厂:通过配置文件动态注入类名,支持热插拔

  • 反射 + 注册表:消除 switch 分支,提升扩展性

如果你想进一步封装登录逻辑,可以使用策略 + 工厂模式组合,写成:

LoginStrategy strategy = LoginStrategyFactory.get(userType);
strategy.authenticate(request);

 完整代码:
 

package com.Factory_Pattern;import java.util.HashMap;
import java.util.Map;public class Final {public static void main(String[] args) {String userType = "oauth";String username = "admin";String credential = "oauth_token";LoginStrategy strategy = LoginStrategyFactory.getStrategy(userType);boolean success = strategy.login(username, credential);System.out.println(success ? "✅ 登录成功!" : "❌ 登录失败!");}
}interface LoginStrategy {boolean login(String username, String credential);
}class UserLoginStrategy implements LoginStrategy {@Overridepublic boolean login(String username, String password) {System.out.println("【普通用户】登录验证...");return "user".equals(username) && "123".equals(password);}
}class AdminLoginStrategy implements LoginStrategy {@Overridepublic boolean login(String username, String password) {System.out.println("【管理员】登录验证...");return "admin".equals(username) && "adminpass".equals(password);}
}class OAuthLoginStrategy implements LoginStrategy {@Overridepublic boolean login(String username, String token) {System.out.println("【OAuth】登录验证...");return "oauth_token".equals(token);}
}class LoginStrategyFactory {private static final Map<String, LoginStrategy> STRATEGY_MAP = new HashMap<>();static {STRATEGY_MAP.put("user", new UserLoginStrategy());STRATEGY_MAP.put("admin", new AdminLoginStrategy());STRATEGY_MAP.put("oauth", new OAuthLoginStrategy());}public static LoginStrategy getStrategy(String userType) {LoginStrategy strategy = STRATEGY_MAP.get(userType.toLowerCase());if (strategy == null) {throw new IllegalArgumentException("未知用户类型: " + userType);}return strategy;}
}

六、结语

工厂模式作为 Java 最常用的设计模式之一,真正的精髓在于解耦与扩展性。尤其在业务不断演进、需求不断变化的环境中,工厂模式提供了一种优雅的应对方式。学会了工厂模式,你将能更从容地面对对象创建、逻辑分发和模块扩展等挑战。如果你觉得本文对你有帮助,欢迎点赞、评论和分享,让更多人了解并掌握设计模式的魅力!

相关文章:

Java 工厂设计模式详解:用统一入口打造灵活可扩展的登录系统----掌握 Spring 源码的基础第一步

一、前言 在实际开发中&#xff0c;我们经常面临以下场景&#xff1a; 系统支持多种登录方式&#xff08;用户名密码、管理员登录、OAuth 登录、短信登录等&#xff09; 每种登录方式的认证逻辑不同 我们希望对外提供一个统一的接口调用&#xff0c;而不暴露具体实现 这个…...

Spring Boot管理Spring MVC

Spring Boot真正的核心功能是自动配置和快速整合&#xff0c;通常Spring Boot应用的前端MVC框架依然使用Spring MVC。Spring Boot提供的spring-boot-starter-web启动器嵌入了Spring MVC的依赖&#xff0c;并为Spring MVC提供了大量自动配置&#xff0c;可以适用于大多数Web开发…...

在 Kali Linux 上安装 Java OpenJDK 8(详细指南)

前置知识 Kali Linux&#xff1a;本文假设你使用的是最新版本的 Kali Linux&#xff0c;且具有管理员权限&#xff08;sudo 或 root 权限&#xff09;。OpenJDK 8&#xff1a;OpenJDK 是 Java Development Kit (JDK) 的开源实现&#xff0c;包含运行 Java 程序所需的 Java Run…...

Windows单机模拟MySQL主从复制

这里写自定义目录标题 下载MySQL ZIP压缩包安装主库1、创建配置文件2、安装服务3、初始化数据库4、启动服务5、配置主库 安装从库1、配置ini文件2、安装服务3、初始化数据库4、启动服务5、配置从库6、验证从库状态 操作主库验证 下载MySQL ZIP压缩包 https://dev.mysql.com/do…...

Wifi密码查看软件V1.0

⭐本软件用于查看电脑连接过所有WiFi密码&#xff0c;不具备破解功能。 可在忘记WiFi密码或他人输入密码自己不知道的情况下使用。 ⭐⭐为便于快速分享&#xff0c;加入双击【密码】列可将WIFI密码复制在粘贴板。 ⭐⭐⭐双击【名称】列可生成用于手机连接的二维码进行显示&…...

分布式日志治理:Log4j2自定义Appender写日志到RocketMQ

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

【口腔粘膜鳞状细胞癌】文献阅读3

文献 Single-cell transcriptomic analysis uncovers the origin and intratumoral heterogeneity of parotid pleomorphic adenoma 单细胞转录组学分析揭示了腮腺多形性腺瘤的起源和瘤内异质性 IF:10.8中科院分区:1区 医学WOS分区:Q1 摘要 多形性腺瘤 &#xff08;PA&#…...

【2025“华中杯”大学生数学建模挑战赛】C题:就业状态分析与预测 详细解题思路

目录 2025“华中杯”大学生数学建模挑战赛C题 详细解题思路一、问题一1.1 问题分析1.2 数学模型 1.3 Python代码1.4 Matlab代码 二、问题二2.1 问题分析2.2 数学模型 2.3 Python代码2.4 Matlab代码 三、问题三3.1 问题分析 四、问题四4.1 问题分析与数学模型 2025“华中杯”大学…...

扫雷-C语言版

C语言扫雷游戏设计&#xff08;完整版&#xff09; 游戏背景 扫雷是一款经典的益智类单人电脑游戏&#xff0c;最早出现在1960年代&#xff0c;并在1990年代随着Windows操作系统而广为人知。游戏目标是在不触发任何地雷的情况下&#xff0c;揭开所有非地雷的格子。玩家需要根…...

【fisco bcos】基于ABI调用智能合约

参考官方文档&#xff1a;https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/docs/sdk/java_sdk/assemble_transaction.html 先放一下智能合约&#xff1a; &#xff08;就是一个很简单的插入和查找嗯&#xff09; pragma solidity ^0.4.25; pragma experimental…...

Delphi Ini文件对UTF8支持不爽的极简替代方案

如题&#xff0c;没太多废话&#xff0c;直接复制走即可。 unit uConfig;interfaceuses classes, Sysutils;typeTConfig class privateFFileName: String;FConfig:TStringList; protectedpublicconstructor Create(ConfigFile:String);destructor Destroy;property FileName…...

【LangChain实战】构建下一代智能问答系统:从RAG架构到生产级优化

打破传统问答系统的次元壁 当ChatGPT在2022年掀起AI革命时&#xff0c;开发者们很快发现一个残酷现实&#xff1a;通用大模型在专业领域的表现如同拿着地图的盲人&#xff0c;既无法理解企业私有数据&#xff0c;也无法保证事实准确性。这催生了RAG&#xff08;检索增强生成&a…...

C++编译与链接:从源码到可执行文件的魔法之旅(Visual Studio实践)

文章目录 **C++编译与链接:从源码到可执行文件的魔法之旅(Visual Studio实践)****一、C++编译器的工作流程****二、Visual Studio环境配置实战****三、示例项目:Hello World全流程解析****四、高级技巧与工具链****五、总结与参考资料**C++编译与链接:从源码到可执行文件的…...

RL中的rollout和episode的区别请问是啥

很好的问题兄弟&#xff0c;rollout 和 episode 在强化学习&#xff08;RL&#xff09;里经常一起出现&#xff0c;虽然有重叠&#xff0c;但含义和使用语境还是有区别的&#xff1a; ✅ 一句话总结&#xff1a; Episode 是一个完整的任务过程&#xff08;从起点到终点&#xf…...

个人博客系统后端 - 用户信息管理功能实现指南(上)

本文记录了如何实现用获取户信息&#xff0c;用户信息更新&#xff0c;用户头像上传三大基础功能 先上接口实现截图&#xff1a; 一、项目结构概览 先介绍一下 个人博客系统采用了标准的 Spring Boot 项目结构&#xff0c;用户功能相关的文件主要分布在以下几个目录&#xff1a…...

判断一个整数是否为素数

#include <stdio.h> #include <stdbool.h> // 引入布尔类型// 函数声明&#xff1a;判断一个整数是否为素数 bool isPrime(int num);int main() {int number;// 提示用户输入一个整数printf("请输入一个整数&#xff1a;");scanf("%d", &n…...

具身智能机器人学习路线全解析

一、引言 具身智能机器人作为融合了机器人学、人工智能、认知科学等多领域知识的前沿技术&#xff0c;正逐渐改变着我们的生活和工作方式。从工业制造到家庭服务&#xff0c;从医疗护理到太空探索&#xff0c;具身智能机器人都展现出了巨大的潜力。对于想要深入了解和学习这一…...

虚幻基础:ue引擎的碰撞

文章目录 碰撞&#xff1a;碰撞体间 运动后 产生碰撞的行为——由引擎负责&#xff0c;并向各自发送事件忽略重叠阻挡 碰撞体类型模式纯查询&#xff1a;不清楚具体作用可以阻挡 actor碰撞(武器&#xff1a;刀/子弹)子组件可以产生阻挡 角色的碰撞只有根组件可以阻挡&#xff0…...

写项目时一些疑惑:组件间的通信、createDownloadUrl和DownloadUrl,ArrayBuffer与Blob等

目录 一、[vite] Internal server error: No known conditions for "./lib/locale/lang/zh-cn" specifier in "element-plus" package 二、可以用vue和JS的代码片段,但是用不了html的代码片段 三、meta是什么东西 四、为什么代码保持一致,但是时间轴始…...

TAS启动与卸载

3. 启动TAS&#xff08;Thin-Agent服务&#xff09; TAS在安装完成后通常会自动启动&#xff0c;并在系统重启时自启。如需手动启动&#xff0c;请按以下步骤操作&#xff1a; &#xfffc; 3.1 在Windows上启动TAS 1. 打开 Windows服务管理器&#xff1a; ◦ 按下 Win R&…...

对抗生成进化:基于DNA算法的AIGC检测绕过——让AI创作真正“隐形“

一、技术背景与核心思想 2025年&#xff0c;AIGC检测工具&#xff08;如Originality.AI 5.0&#xff09;的识别准确率已达99.3%。本研究提出基于染色体编码的对抗进化框架&#xff08;CAEF&#xff09;&#xff0c;通过模拟生物进化过程动态优化生成模型&#xff0c;成功将检测…...

手动关闭ArcGIS与ArcGIS Online连接的方法

【关闭软件启动时ArcGIS与ArcGIS Online连接方法】 打开C盘找到文件夹“C:\Program Files (x86)\Common Files\ArcGIS\bin”&#xff0c;如下图&#xff0c;删除“ArcGISConnection.exe”与“ArcGISConnectionTest.exe”文件&#xff0c;软件下次启动的时候就不会建立与ArcGIS …...

SpringBoot条件注解全解析:核心作用与使用场景详解

目录 引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、ConditionalOnClass和ConditionalOnMissingClass2、ConditionalOnBean和ConditionalOnMissingBean3、ConditionalOnProperty4、ConditionalOnWebApplication和ConditionalOnNotWebApplication5、ConditionalO…...

android11通过白名单卸载安装应用

目录 1.源码路径: 2.准备文件package.conf: 3.安装方法installPackagesLI 4.卸载方法deletePackageX 1.源码路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java public static final String WHITELIST_PATH="/data/misc/pa…...

大M法处理非线性约束线性化

在电力系统优化问题中&#xff0c;大M法&#xff08;Big M Method&#xff09;是一种经典的处理非线性约束线性化的技术&#xff0c;尤其适用于混合整数线性规划&#xff08;MILP&#xff09;问题。 其核心思想是通过引入足够大的常数M和辅助变量&#xff08;如二元变量或松弛…...

【网络安全】谁入侵了我的调制解调器?(一)

文章目录 我被黑了159.65.76.209,你是谁?黑客攻击黑客?交出证据三年后我被黑了 两年前,在我家里使用家庭网络远程办公时,遇到了一件非常诡异的事情。当时,我正在利用一个“盲 XXE 漏洞”,这个漏洞需要借助一个外部 HTTP 服务器来“走私”文件。为了实现这一点,我在 AW…...

【Nokia 7360 ISAM局端】7360局端升级步骤

引言 Nokia 7360 ISAM局端是当前主流的OLT局端之一,在测试ONT产品中经常需要对接7360局端,特别是欧美等海外运营商。测试过程中经常需要升级OLT版本,以便对齐前方客户的现网环境。本文介绍将Nokia 7360 ISAM局端升级到L6GPAA65.669版本的详细步骤。 连接带外管理口 将维护…...

await 在多线程,子线程中的使用

await 在多线程,子线程中的使用 await self.send_reply(user, user, user, auto_content, reply) 这行代码是在一个异步函数里调用类的实例方法 send_reply 代码含义 1. await 关键字 在 Python 的异步编程里,await 关键字的作用是暂停当前异步函数的执行,直到 await 后…...

主数据管理:企业数字化转型的 “数据基石“ 如何为 AI 筑基?

引言&#xff1a;当数据成为新石油&#xff0c;谁在炼制 "高纯度燃料"&#xff1f; 在数字化转型的浪潮中&#xff0c;企业宛如行驶在数据海洋中的巨轮&#xff0c;AI 则是驱动巨轮破浪前行的引擎。但引擎能否高效运转&#xff0c;取决于燃料的纯度 —— 这正是主数…...

使用源码编译安装golang的docker版

编译规则 1.4之前用C写的&#xff0c;1.4可编译后续一直到1.9版本&#xff0c;后续版本实现了自举&#xff0c;后续版本是go写的&#xff0c;基本上相互低2个版本能编译出新版本。 Go < 1.4&#xff1a;C 工具链。 1.5 < Go < 1.19&#xff1a;Go 1.4 编译器。 1.20…...