项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/design-demo
项目结构如下(示例):

代码如下(示例):
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.3
com.example
design-demo
0.0.1-SNAPSHOT
design-demo
Demo project for Spring Boot
1.8
UTF-8
UTF-8
2.3.7.RELEASE
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.statemachine
spring-statemachine-core
2.1.3.RELEASE
org.springframework.boot
spring-boot-maven-plugin
代码如下(示例):
package com.example.designdemo.controller;
import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:26
* @Description:
*/
@RestController
@RequestMapping("/pay")
public class PayController {
@Autowired
private PayService payService;
@PostMapping("/dopay")
public Boolean dopay(@RequestBody PayBody payBody){
return payService.pay(payBody);
}
}
代码如下(示例):
package com.example.designdemo.service;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:28
* @Description:
*/
public interface PayService {
Boolean pay(PayBody payBody);
}
代码如下(示例):
package com.example.designdemo.service.impl;
import com.example.designdemo.handler.PayHandler;
import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.stereotype.Service;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description:
*/
@Service
public class PayServiceImpl implements PayService {
@Override
public Boolean pay(PayBody payBody) {
//付款逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = PayHandler.zfbpay(payBody);
}else if(type == 1){
//微信支付逻辑
flag = PayHandler.wxbpay(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = PayHandler.bankbpay(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;
}
}
代码如下(示例):
package com.example.designdemo.pojo;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description: 属性的类型这里都是简写,实战项目肯定不会写这么粗糙,这里主要是写设计模式相关,细节就不抠了。
*/
public class PayBody {
//账号
private String account;
//支付类型
private int type;
//产品信息
private String product;
//金额
private int amcount;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public int getAmcount() {
return amcount;
}
public void setAmcount(int amcount) {
this.amcount = amcount;
}
}
代码如下(示例):
package com.example.designdemo.handler;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:42
* @Description:
*/
@Component
public class PayHandler {
public static boolean zfbpay(PayBody payBody) {
//详细调用支付宝提供的第三方接口
//........................
return true;
}
public static boolean wxbpay(PayBody payBody) {
//详细调用支付宝提供的第三方接口
//........................
return true;
}
public static boolean bankbpay(PayBody payBody) {
//详细调用支付宝提供的第三方接口
//........................
return true;
}
}
正常这段代码逻辑是没什么问题的,初中级这么写也没什么毛病。
但是对于高级开发而言,就需要思考它的一个扩展性,封装性了,这里举个例子:
假设PayServiceImpl.pay是由你来写的,PayHandler.zfbpay、PayHandler.wxbpay、PayHandler.bankbpay是由另外一个同事来写的,并且以jar包的形式集成到你的项目中,提供给你调用的。
弊端:
后面我们一步一步进行改造,最终的目标就是解决上述的问题
首先对上述代码进行改造,先引入策略模式
代码如下(示例):
package com.example.designdemo.service.impl;
import com.example.designdemo.context.PayContext;
import com.example.designdemo.handler.PayHandler;
import com.example.designdemo.inter.BankPayStrategy;
import com.example.designdemo.inter.WxPayStrategy;
import com.example.designdemo.inter.ZfbPayStrategy;
import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.stereotype.Service;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description:
*/
@Service
public class PayServiceImpl implements PayService {
@Override
public Boolean pay(PayBody payBody) {
/* //传统模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = PayHandler.zfbpay(payBody);
}else if(type == 1){
//微信支付逻辑
flag = PayHandler.wxpay(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = PayHandler.bankbpay(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
//引入策略模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = new PayContext(new ZfbPayStrategy()).execute(payBody);
}else if(type == 1){
//微信支付逻辑
flag = new PayContext(new WxPayStrategy()).execute(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = new PayContext(new BankPayStrategy()).execute(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;
}
}
代码如下(示例):
package com.example.designdemo.context;
import com.example.designdemo.inter.PayStrategy;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:30
* @Description: 起到承上启下的作用
*/
public class PayContext {
private PayStrategy payStrategy;
public PayContext(PayStrategy payStrategy){
this.payStrategy = payStrategy;
}
public Boolean execute(PayBody payBody){
return this.payStrategy.pay(payBody);
}
}
代码如下(示例):
package com.example.designdemo.inter;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:23
* @Description: 引入策略模式
*/
public interface PayStrategy {
//未来顶PayHandler里面的三个
Boolean pay(PayBody payBody);
}
代码如下(示例):
package com.example.designdemo.inter;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.bankpay
*/
public class BankPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
代码如下(示例):
package com.example.designdemo.inter;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.wxpay
*/
public class WxPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
代码如下(示例):
package com.example.designdemo.inter;
import com.example.designdemo.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.zfbpay
*/
public class ZfbPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
弊端:
创建pay目录
代码如下(示例):
package com.example.designdemo.pay.context;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.pay.strategy.PayStrategy;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:30
* @Description: 起到承上启下的作用
*/
public class PayContext {
private PayStrategy payStrategy;
public PayContext(PayStrategy payStrategy){
this.payStrategy = payStrategy;
}
public Boolean execute(PayBody payBody){
return this.payStrategy.pay(payBody);
}
}
代码如下(示例):
package com.example.designdemo.pay.factory;
import com.example.designdemo.pay.strategy.PayStrategy;
import com.example.designdemo.pay.strategyEnum.StrategyEnum;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:53
* @Description: 策略工厂 工厂类依靠策略枚举返回策略类 后面都不需要修改了,因为它是一个无状态的
*/
public class StrategyFactory {
public static PayStrategy getPayStrategy(StrategyEnum strategyEnum){
PayStrategy payStrategy = null;
try {
payStrategy = (PayStrategy)Class.forName(strategyEnum.getValue()).newInstance();
} catch (Exception e) {
//异常信息打印
}
return payStrategy;
}
}
代码如下(示例):
package com.example.designdemo.pay.pojo;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description: 属性的类型这里都是简写,实战项目肯定不会写这么粗糙,这里主要是写设计模式相关,细节就不抠了。
*/
public class PayBody {
//账号
private String account;
//支付类型
private int type;
//产品信息
private String product;
//金额
private int amcount;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public int getAmcount() {
return amcount;
}
public void setAmcount(int amcount) {
this.amcount = amcount;
}
}
代码如下(示例):
package com.example.designdemo.pay.strategy;
import com.example.designdemo.pay.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:23
* @Description: 引入策略模式
*/
public interface PayStrategy {
//未来顶PayHandler里面的三个
Boolean pay(PayBody payBody);
}
代码如下(示例):
package com.example.designdemo.pay.strategy;
import com.example.designdemo.pay.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.bankpay
*/
public class BankPayStrategy implements PayStrategy {
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
代码如下(示例):
package com.example.designdemo.pay.strategy;
import com.example.designdemo.pay.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.wxpay
*/
public class WxPayStrategy implements PayStrategy {
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
代码如下(示例):
package com.example.designdemo.pay.strategy;
import com.example.designdemo.pay.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:25
* @Description: 替换掉PayHandler.zfbpay
*/
public class ZfbPayStrategy implements PayStrategy {
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
代码如下(示例):
package com.example.designdemo.pay.strategyEnum;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:56
* @Description: 准备使用反射
*/
public enum StrategyEnum {
ZfbPayStrategy("com.example.designdemo.pay.strategy.ZfbPayStrategy"),
WxPayStrategy("com.example.designdemo.pay.strategy.WxPayStrategy"),
BankPayStrategy("com.example.designdemo.pay.strategy.BankPayStrategy");
String value = "";
StrategyEnum(String value){
this.value = value;
}
public String getValue(){
return this.value;
}
}
代码如下(示例):
package com.example.designdemo.service.impl;
//import com.example.designdemo.context.PayContext;
//import com.example.designdemo.handler.PayHandler;
//import com.example.designdemo.inter.BankPayStrategy;
//import com.example.designdemo.inter.WxPayStrategy;
//import com.example.designdemo.inter.ZfbPayStrategy;
//import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.pay.context.PayContext;
import com.example.designdemo.pay.factory.StrategyFactory;
import com.example.designdemo.pay.strategyEnum.StrategyEnum;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.stereotype.Service;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description:
*/
@Service
public class PayServiceImpl implements PayService {
@Override
public Boolean pay(PayBody payBody) {
/* //传统模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = PayHandler.zfbpay(payBody);
}else if(type == 1){
//微信支付逻辑
flag = PayHandler.wxpay(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = PayHandler.bankbpay(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
/* //引入策略模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = new PayContext(new ZfbPayStrategy()).execute(payBody);
}else if(type == 1){
//微信支付逻辑
flag = new PayContext(new WxPayStrategy()).execute(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = new PayContext(new BankPayStrategy()).execute(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
//引入工厂模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.ZfbPayStrategy)).execute(payBody);
}else if(type == 1){
//微信支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.WxPayStrategy)).execute(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.BankPayStrategy)).execute(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;
}
}
代码如下(示例):
package com.example.designdemo.service;
//import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.pay.pojo.PayBody;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:28
* @Description:
*/
public interface PayService {
Boolean pay(PayBody payBody);
}
代码如下(示例):
package com.example.designdemo.controller;
//import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:26
* @Description:
*/
@RestController
@RequestMapping("/pay")
public class PayController {
@Autowired
private PayService payService;
@PostMapping("/dopay")
public Boolean dopay(@RequestBody PayBody payBody){
return payService.pay(payBody);
}
}
缺点:
代码如下(示例):
package com.example.designdemo.pay.facade;
import com.example.designdemo.pay.context.PayContext;
import com.example.designdemo.pay.strategy.PayStrategy;
import com.example.designdemo.pay.factory.StrategyFactory;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.pay.strategyEnum.StrategyEnum;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 11:27
* @Description: 门面模式,最终只暴露门面即可,门面就是我们的超级封装
*/
public class StrategyFacade {
public static Boolean pay(PayBody payBody){
//获取策略枚举
StrategyEnum strategyEnum = getStrategyEnum(payBody.getType());
//获取策略对象
PayStrategy payStrategy = StrategyFactory.getPayStrategy(strategyEnum);
//生成策略上下文
PayContext payContext = new PayContext(payStrategy);
//进行付款
Boolean execute = payContext.execute(payBody);
return execute;
}
private static StrategyEnum getStrategyEnum(int type) {
switch (type){
case 0:
return StrategyEnum.ZfbPayStrategy;
case 1:
return StrategyEnum.WxPayStrategy;
case 2:
return StrategyEnum.BankPayStrategy;
default:
return null;
}
}
}
代码如下(示例):
package com.example.designdemo.service.impl;
//import com.example.designdemo.context.PayContext;
//import com.example.designdemo.handler.PayHandler;
//import com.example.designdemo.inter.BankPayStrategy;
//import com.example.designdemo.inter.WxPayStrategy;
//import com.example.designdemo.inter.ZfbPayStrategy;
//import com.example.designdemo.pojo.PayBody;
import com.example.designdemo.pay.context.PayContext;
import com.example.designdemo.pay.facade.StrategyFacade;
import com.example.designdemo.pay.factory.StrategyFactory;
import com.example.designdemo.pay.strategyEnum.StrategyEnum;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.service.PayService;
import org.springframework.stereotype.Service;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 9:29
* @Description:
*/
@Service
public class PayServiceImpl implements PayService {
@Override
public Boolean pay(PayBody payBody) {
/* //传统模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = PayHandler.zfbpay(payBody);
}else if(type == 1){
//微信支付逻辑
flag = PayHandler.wxpay(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = PayHandler.bankbpay(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
/* //引入策略模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = new PayContext(new ZfbPayStrategy()).execute(payBody);
}else if(type == 1){
//微信支付逻辑
flag = new PayContext(new WxPayStrategy()).execute(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = new PayContext(new BankPayStrategy()).execute(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
/* //引入工厂模式开发支付逻辑
boolean flag = false;
int type = payBody.getType();
if (type == 0) {
//支付宝支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.ZfbPayStrategy)).execute(payBody);
}else if(type == 1){
//微信支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.WxPayStrategy)).execute(payBody);
}else if(type == 2){
//银行卡支付逻辑
flag = new PayContext(StrategyFactory.getPayStrategy(StrategyEnum.BankPayStrategy)).execute(payBody);
}else {
throw new UnsupportedOperationException("unsupport type,please choose o,1,2 ");
}
if (flag) {
//支付成功走后续逻辑
}
return flag;*/
//引入门面模式开发支付逻辑
Boolean flag = StrategyFacade.pay(payBody);
if (flag) {
//支付成功走后续逻辑
}
return flag;
}
}
优点:
代码如下(示例):
package com.example.designdemo.pay.factory;
import com.example.designdemo.pay.strategy.PayStrategy;
import com.example.designdemo.pay.strategyEnum.StrategyEnum;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: zhiwei Liao
* @Date: 2022/9/25 10:53
* @Description: 策略工厂 工厂类依靠策略枚举返回策略类 后面都不需要修改了,因为它是一个无状态的 使用饿汉单例模式创建
*/
public class StrategyFactory {
private static final Map strategyMaps = new ConcurrentHashMap();
public static PayStrategy getPayStrategy(StrategyEnum strategyEnum){
PayStrategy payStrategy = strategyMaps.get(strategyEnum.getValue());
try {
payStrategy = (PayStrategy) Class.forName(strategyEnum.getValue()).newInstance();
strategyMaps.put(strategyEnum.getValue(), payStrategy);
} catch (Exception e) {
//异常信息打印
}
return payStrategy;
}
}
这里没有使用传统的单例模式,我需要在StrategyFactory里面获取PayStrategy所有的类型,所以这里面使用了一个map进行存储,同时为了保证线程安全使用ConcurrentHashMap保证线程安全。
传统的单例模式:



单例模式的优点:
引入单例模式,解决了策略模式 + 工厂模式 + 门面模式中StrategyFactory.getPayStrategy每次调用都需要进行一次反射创建对象。
最后我们的项目结构如下(示例):(仅展开的类有用到)
