Spring中常见的设计模式——策略模式
策略模式(Strategy Pattern)是指定义了算法家族病分别封装起来,让他们之间可以互相替换,此模式是的算法的变化不会影响使用算法的用户。
一、策略模式的应用场景
策略模式的应用场景如下:
- 系统中有很多类,而他们的区别仅仅在于行为不同。
- 一个系统需要动态的在几种算法中选择一种
二、用策略模式实现选择支付方式的业务场景
一个常见的应用场景就是大家在支付时会提示选择支付方式,如果用户未选,系统会使用默认的支付方式进行结算。下面我们用策略模式来模拟此业务场景:
/**
* 定义支付规范和支付逻辑
*/
public abstract class Payment { //支付类型
public abstract String getName(); //查询余额
protected abstract double queryBalance(String uid); //扣款支付
public PayState pay(String uid, double amount) {
if (queryBalance(uid) < amount) {
return new PayState(500, "支付失败", "余额不足");
}
return new PayState(200, "支付成功", "支付金额:" + amount);
}
}
扣款支付逻辑简单做一下:
/**
* 支付逻辑
*/
public class PayState {
private int code;
private Object data;
private String msg; public PayState(int code, String msg, String data) {
this.code = code;
this.data = data;
this.msg = msg;
} public String toString() {
return ("支付状态:[" + code + "]," + msg + ",交易详情:" + data);
}
}
定义两种支付方式:
/**
* 支付宝
*/
public class AliPay extends Payment {
@Override
public String getName() {
return "支付宝";
} @Override
protected double queryBalance(String uid) {
return 900;
}
} /**
* 微信支付
*/
public class WechatPay extends Payment {
@Override
public String getName() {
return "微信支付";
} @Override
protected double queryBalance(String uid) {
return 256;
}
}
支付策略管理类
/**
* 支付策略管理类
*/
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String DEFAULT_PAY = ALI_PAY; private static Map<String, Payment> payStrategy = new HashMap<>(); static {
payStrategy.put(ALI_PAY, new AliPay());
payStrategy.put(WECHAT_PAY, new WechatPay());
} public static Payment get(String payKey) {
if (!payStrategy.containsKey(payKey)) {
return payStrategy.get(DEFAULT_PAY);
}
return payStrategy.get(payKey);
}
}
创建订单:订单支付时因为支付方式已经在集合内并且可以通过key得到,所以不用switch 和if else进行赘述
/**
* 订单类
*/
public class Order {
private String uid;
private String orderId;
private Double amount; public Order(String uid, String orderId, Double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
} //完美解决了switch的过程,不需要写switch和if...else if
public PayState pay() {
return pay(PayStrategy.DEFAULT_PAY);
} public PayState pay(String payKey) {
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用:" + payment.getName());
System.out.println("本次交易金额为:" + amount + ",扣款中...");
return payment.pay(uid, amount);
}
}
测试类:
public class PayStrategyTest {
public static void main(String[] args) {
//创建订单
Order order = new Order("1", "202001080001", 324.45); //选择支付方式:支付宝支付
System.out.println(order.pay(PayStrategy.ALI_PAY));
}
}
三、策略模式在源码中的体现
1.JDK中的应用
首先看比较常见的比较器——Compare接口,常用的compare()方法就是常见的策略模式的抽象实现,Comparator接口下面有非常多的实现类,我们把Comparator接口作为传入实现排序策略例如:
public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) {
if (cmp == null)
cmp = NaturalOrder.INSTANCE;
int n = a.length, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
TimSort.sort(a, 0, n, cmp, null, 0, 0);
else
new ArraysParallelSortHelpers.FJObject.Sorter<T>
(null, a,
(T[])Array.newInstance(a.getClass().getComponentType(), n),
0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
}
还有TreeMap类的构造方法:
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
2.Spring源码中的应用
Spring的初始化采用了策略模式,不同类型的类采用不同的初始化策略。
public interface InstantiationStrategy {
Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3) throws BeansException; Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3, Constructor<?> var4, Object... var5) throws BeansException; Object instantiate(RootBeanDefinition var1, String var2, BeanFactory var3, Object var4, Method var5, Object... var6) throws BeansException;
}
四、策略模式的优缺点
策略模式的优点如下:
- 策略模式符合开闭原则。
- 策略模式可避免使用多重条件语句,如switch if else。
- 使用策略模式可以提高算法的保密性和安全性。
策略模式的缺点如下:
- 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
- 代码中会产生非常多的策略类,增加了代码的维护难度。
五、委派模式与策略模式综合应用
委派模式:DispatcherServlet 根据url对应Controller 用的是if else, 应该将对应关系放入容器中,利用URL找到对应的Controller,这样做成策略模式。
Spring中常见的设计模式——策略模式的更多相关文章
- Spring中常见的设计模式——代理模式
一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...
- Spring中常见的设计模式——委派模式
一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...
- Spring中常见的设计模式——工厂模式
一.简单工厂模式 简单工厂模式(Simple Factory Pattern)由一个工厂对象决定创建哪一种产品类的实例,简单工厂模式适用于工厂类负责创建对象较少的情况,且客户端只需要传入工厂类的参数, ...
- Spring中常见的设计模式——原型模式
1.原型模式应用场景 当遇到大量耗费劳动力的 get,set赋值场景时,如下: public class SetGetParam { public void setParam(UserDto user ...
- Spring中常见的设计模式——模板模式
一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...
- Spring中常见的设计模式——适配器模式
一.适配器模式的应用场景 适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期待的另一个接口,使原本接口不兼容的类可以一起工作,属于构造设计模式. 适配器适用于以下几种业务场景: ...
- 设计模式:JDK和Spring中常见的设计模式
设计模式 总结 类 工厂模式 封装创建过程,只对结果负责 BeanFactory.Calender 单例模式 全局唯一 ApplicationContext.Calender 原型模式 多重影分身之术 ...
- Spring中常见的设计模式——单例模式
一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletCon ...
- spring 中常用的设计模式
一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...
随机推荐
- Android Xutils框架使用问题及解决办法
刚刚写了篇博客,提了下在使用XUtils时遇到的一个问题Android Xutils框架HttpUtil Get请求缓存问题 ,既然已经提起来这个问题,那我想了下,就把之前使用Xutils时遇到的几个 ...
- 对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解
1. 先看一段代码 def is_login(func): def foo(*args,**kwargs): return func(*args,**kwargs) return foo def te ...
- 【Vue】基于nodejs的vue项目打包编译部署
一·项目编译 1·进入项目目录下的终端执行命令 npm run build 正常情况如下图,如遇到错误不会编译成功,且编译后的html文件不能正常渲染. 2·编译完成后进入项目下的dist目录运行生成 ...
- js中的数据类型及常用属性和方法
JavaScript 字符串 字符串(或文本字符串)是一串字符(比如 "Bill Gates").字符串被引号包围.您可使用单引号或双引号您可以在字符串内使用引号,只要这些引号与包 ...
- 京东基于Spark的风控系统架构实践和技术细节
京东基于Spark的风控系统架构实践和技术细节 时间 2016-06-02 09:36:32 炼数成金 原文 http://www.dataguru.cn/article-9419-1.html ...
- 免费开源3D模型设计软件汇总
免费开源3D模型设计软件汇总 3D 打印需要先通过计算机辅助设计(CAD)进行建模,再将建好的3D模型“分割”成逐层的截面,从而指导3D打印机进行逐层打印.因此用于3D打印的3D模 型大都储存或输出成 ...
- P1024 硬币问题
题目描述 假设现在有面值为1, 5, 10, 50, 100, 500的硬币各无限枚, 如果用这些硬币来支付A元, 最少需要多少枚硬币? 输入格式 一个整数A(0<=A<=1e9), 表示 ...
- H3C查看系统启动配置文件
- 【t068】智慧碑
Time Limit: 1 second Memory Limit: 128 MB [问题描述] DIABLO魔王和Mini都有三种属性,体力点,攻击点,以及集气点. 两人的攻击方式是这样的:采用回合 ...
- excel转换成实体
package com.cinc.ecmp.utils; import java.io.IOException; import java.io.InputStream; import java.lan ...