java8 策略模式_JAVA设计模式之策略模式

article/2025/10/4 17:35:16

策略模式:在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

策略模式三种角色:

1、环境上下文(Context)角色:持有一个Strategy引用,委托策略变量调用具体策略所实现的策略接口中的方法。

2、策略(Strategy)角色:抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需接口。

3、具体策略(ConcreteStrategy)角色:具体实现策略接口的类,包装了相关的算法或行为。

废话不多说,直接上手:

项目背景:聚合支付平台,涉及到多种支付方式选择。

环境准备:JDK8、springboot2.0.x、idea工具、mysql数据库...

传统做法:

f74d814f89c96423484843b76d9b36a8.png

解释:可以看到需要根据支付code码,来调用不同的支付方式,可能还会有其他更多支付方式...显而易见,只是调用三方接口处理逻辑不同,但最终都是封装html表单给支付接口。这里使用if判断,也是目前大多数人的处理方式,简单直观,但是后期的代码维护性很差!

使用策略模式:

先根据需要创建一个支付渠道关系表

2c73edc27a424c2b9fbc55c97ada7407.png

(可以根据需要增加其他字段,如回调url,是否删除等字段,建议将这块放到后台管理中)

整体流程可以缩概为如下图所示:

20b6b695f02f803535b375cd80b0d5b7.png

弄懂整个原理和流程,下面进入开发阶段

1、定义mapper(这里用的是springboot整合mybatis):

SELECT id as id ,channel_name as channelName ,channel_id as channelId,strategy_bean_id AS strategybeanid

FROM payment_channel where channel_id=#{payCode}

1、定义具体策略ConcreteStrategy:

public interface PayStrategy {

/**

* 策略模式算法核心

* @return

*/

String toPayM();

}

2、定义具体策略Strategy:

@Component

public class AliPayStrategy implements PayStrategy {

/**

* 策略模式算法核心

*

* @return

*/

@Override

public String toPayM() {

return "使用支付宝支付....";

}

}

@Component

public class WXPayStrategy implements PayStrategy {

/**

* 策略模式算法核心

*

* @return

*/

@Override

public String toPayM() {

return "使用微信支付....";

}

}

@Component

public class YinLIanPayStrategy implements PayStrategy {

/**

* 策略模式算法核心

*

* @return

*/

@Override

public String toPayM() {

return "使用银联支付....";

}

}

3、实现环境上下文Context:

@Component

public class PayContextStrategy {

@Resource

private PaymentChannelMapper paymentChannelMapper;

/**

* 1、根据payCode从数据库中获取对应的beanId

* 2、根据beanId从spring容器中获取对应的实例

* 3、执行对应支付方法

* 4、建议优化:可将数据存储在内存中,减少查询数据库的消耗

* @param payCode

* @return

*/

public String toPayM(String payCode){

PaymentChannelEntity entity = paymentChannelMapper.getPaymentChannel(payCode);

if (entity == null || StringUtils.isEmpty(entity.getStrategyBeanId())){

return "参数错误,没有对应渠道信息";

}

PayStrategy payStrategy = SpringUtils.getBean(entity.getStrategyBeanId(),PayStrategy.class);

return payStrategy.toPayM();

}

}

至此,代码开发完毕~~

可以写个demo试下是否成功

@RestController

public class PayController {

@Autowired

private PayContextStrategy payContextStrategy;

@GetMapping("/toPayM")

public String toPayM(String payCode){

return payContextStrategy.toPayM(payCode);

}

}

17413918379e914e034f4c539e5325a6.png

注意:这里有个细节问题,数据库存储的beanId一定要跟我们定义的bean保持一致,否则根据beanId去spring容器中获取实例对象会失败!

附根据beanId获取对应实例对象的utils

/**

* 根据beanId 从spring容器中获取对象

*/

@Component

public class SpringUtils implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

this.applicationContext = applicationContext;

}

//获取applicationContext

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

//通过name获取 Bean.

public static Object getBean(String name){

return getApplicationContext().getBean(name);

}

//通过class获取Bean.

public static T getBean(Class clazz){

return getApplicationContext().getBean(clazz);

}

//通过name,以及Clazz返回指定的Bean

public static T getBean(String name,Class clazz){

return getApplicationContext().getBean(name, clazz);

}

}

优点:策略模式在实际开发中,解决多重if判断问题,便于后期代码维护,增强可读性;

缺点:如果后期策略类型增多,定义类也会相应增多,增加代码量。

完~


http://chatgpt.dhexx.cn/article/tq2y3yG1.shtml

相关文章

git如何提交代码

代码提交 代码提交一般有五个步骤: 1.查看目前代码的修改状态 2.查看代码修改内容 3.暂存需要提交的文件 4.提交已暂存的文件 5.同步到服务器 1. 查看目前代码的修改状态 提交代码之前,首先应该检查目前所做的修改,运行git status命令 a)…

修改git提交时间

问题描述: 修改git提交记录的时间 git脚本: 此方法使用github上的开源工具完成。感谢无私的奉献者! 操作步骤: github上下载文件 解压文件夹,把git-redate文件置于git安装目录的\mingw64\libexec\git-core文件夹…

git提交时常用命令

git提交时常用命令 一、git命令 -- 本地仓库与远程仓库建立链接 git init (初始化本地仓库) git remote add origin 远程仓库网址 git remote -v (查看远程仓库) git remote rm origin (删除远程分支)-- checkout多种用法 git checkout 文件名 &#…

git提交分支

1. git提交分支相关 在本地新建分支,保证和远程分支一样 git checkout -b 分支名如果分支已存在,只需要切换的话 git checkout 分支名提交前先把代码拉下来更新一下,确保不会覆盖别人的代码 git pull origin 远程分支(如果有)解决冲突 git …

Git 的提交

1 提交对象 理解Git分支,就需要了解提交及在提交过程中产生的提交对象(commit object)。在进行提交时Git会存储一个提交对象,其中包含一个指针,它指向此次提交时暂存内容的快照。除此之外,提交对象中还包含…

git代码提交

代码提交 代码提交一般有五个步骤: 1.查看目前代码的修改状态 2.查看代码修改内容 3.暂存需要提交的文件 4.提交已暂存的文件 5.同步到服务器 1. 查看目前代码的修改状态 提交代码之前,首先应该检查目前所做的修改,运行git status命令 a…

【git提交】流程

1- git提交(分支合并)操作流程: git 提交代码到自己的分支,并合并到主分支的完整流程 分支 sml , 主分支, master 分支msl上操作 git status git add . git commit -m ‘xxxxxx’ git pull origin master…

git提交规范,规范自己的提交标准

为了规范我的git提交内容,提交的时候commit -m “备注的信息”,但是每个人的备注信息千奇百怪,为了统一,我们进行了git的规范。 首先要全局安装commitizen npm i -g commitizen4.2.4然后安装插件 npm i cz-customizable6.3.0…

git提交常用命令

git 安装 1.在终端,检查git是否安装 git --version 2.没有安装的话,去git官网,下载git 3.安装后,在终端,检查git是否安装 4设置用户名和邮件地址(最好和github的用户名/邮箱保持一致 git config -…

Git 提交规范

1. 背景 Git 是目前世界上最先进的分布式版本控制系统,在我们平时的项目开发中已经广泛使用。而当我们使用Git提交代码时,都需要写Commit Message提交说明才能够正常提交。 git commit -m "提交"然而,我们平时在编写提交说明时&a…

git 提交命令(附加git常用命令)

一、提交到git仓库 1、进入git终端、输入git init指令、会在当前目录生成一个.git的文件夹 git init2、然后通过git status 查看,该指令作用是 列出修改过的(绿色标识)、新创建的(红色标识)、已经暂存但未提交的文件(白色标识) git status3、然后通过git add ind…

git提交

Git提交代码步骤 1.1 第1步:同步远程仓库代码:git pull 提交代码第1步:git pull 同步远程仓库代码到本地 git add / git commit代码之前首先git pull,需先从服务器上面拉取代码,以防覆盖别人代码;如果有…

你真的了解单点登录(SSO)吗? 单点登录实现方式

在程序开发中,特别是网站类开发,会接触到单点登录(SSO),什么是单点登录?单点登录(SSO)有什么用?下面就来详细介绍一下。 1 单点登录 1.1 什么是单点登录 单点登录的英文名叫做:Single Sign On&#xff0…

单点测试与多点测试

最近在使用PAT与Codeup写程序玩,发现这两者的OJ方式不同。 PAT是单点测试,即输入一组测试用例即可输出结果, 而Codeup是多点测试,即输入所有测试用例后才会输出所有输出结果。 在这里写两个最简单的ab求和小程序来说明二者的区别…

什么是单点登录?如何理解单点登录

什么是单点登录? 什么是单点登录? 因为讲了Cookie,讲了Session,这里我觉得有必要说一下单点登录。我们先来看一下什么是单点登录:单点登录(Single Sign On),简称为 SSO,…

单点登录和多点登录

SSO(单点登录)的概念:在一个多系统共存的环境下,用户在一处登录后,就不用再其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。 SSO(单点登录)的应用场景:…

OAuth2.0 实现单点登录

文章目录 OAuth2.0 实现单点登录一、四种授权模式二、搭建验证服务器三、使用 Postman 接口测试四、基于 EnableOAuth2Sso 实现五、基于 EnableResourceServer 实现 🚩🍬5.1 资源服务器🍬5.2 客户端访问🍬5.3 解决远程调用 六、使…

单点登录(SSO)-- 实现单点登录的几种方式

1.为什么需要单点登录 三个角度: 1.1 方便用户的使用:用户登录一次,可以使用不同的服务和页面,省了忘记密码的痛苦1.2 简化开发:SSO让开发人员只要开发一个通用的身份验证框架,就不用为身份验证操心了1.3 …

面试系列:单点登录的知识(一)

大家好,我是车辙,由于目前接手的业务涉及到了单点登录,所以一直在疯狂的去补充这方面的知识。也写下了这篇面试形式的文章,写的不好大家轻点 Diss。 面试开始 在焦急的等待中,一位看上去比较年轻的小伙子走了过来。我…

单点登录实现的几种方式及原理【单点登录】

文章目录 一、什么是单点登录二、单点登录原理三、单点登录实现方式1.基于CookieRedis的单点登录2.分布式session方式实现单点登录3.token验证4.session广播5.CAS 中央认证服务 一、什么是单点登录 单点登录的英文名叫做:Single Sign On(简称SSO&#x…