首页 > 编程语言 >JAVA设计模式——策略模式

JAVA设计模式——策略模式

时间:2023-10-11 18:34:20浏览次数:41  
标签:JAVA url param clazz return 模式 import 设计模式 public

策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。它定义了一系列算法,将每个算法封装起来并使它们可以相互替换。策略模式使算法的变化独立于使用算法的客户端。

在策略模式中,我们有一个上下文对象,该对象包含一个指向策略对象的引用。策略对象实现了一个公共接口,该接口定义了所有策略对象都必须实现的方法。上下文对象在运行时可以将策略对象替换为另一个策略对象,从而改变其行为。

以下是策略模式的一些关键要素:

  1. 上下文(Context):包含一个指向策略对象的引用。

  2. 策略(Strategy):定义了所有策略对象都必须实现的方法。

  3. 具体策略(Concrete Strategy):实现了策略接口的具体算法。

下面是一个简单的示例,说明如何使用策略模式:

// 策略接口
interface Strategy {
    int doOperation(int num1, int num2);
}

// 具体策略1
class OperationAdd implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

// 具体策略2
class OperationSubtract implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

// 具体策略3
class OperationMultiply implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

// 上下文
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

// 测试
public class StrategyPatternDemo {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationSubtract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationMultiply());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

在上面的示例中,我们定义了一个策略接口 Strategy,并实现了三个具体策略类 OperationAddOperationSubtractOperationMultiply。我们还定义了一个上下文类 Context,它包含一个指向策略对象的引用,并提供了一个执行策略的方法 executeStrategy。在测试代码中,我们创建了一个上下文对象,并使用不同的策略对象来执行不同的算法。

 

项目实践:使用策略模式,实现接口回调时支持多种回调方式(http、feign调用等)

第一步:定义回调策略接口


import com.midea.mbf.api.request.CommonReq;

import java.util.List;
import java.util.Map;

/**
 * @since 2023/7/18
 */
public interface CallbackStrategy {

    /**
     * 获取支持的回调类型
     *
     * @return
     */
    String getSupportCallbackType();

    /**
     * 执行回调
     */
    Map<String, Object> executeCallback(String callbackUrl, CommonReq<List<Map<String, Object>>> commonReq);
}

 第二步:定义回调抽象类实现回调策略接口:


import cn.hutool.core.text.CharSequenceUtil;
import com.*.CallbackConstants;
import com.*.AbstractAccessor;
import com.*.Logger;
import com.*.LoggerFactory;
import com.*.CommonReq;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @since 2023/7/18
 */
public abstract class AbstractCallbackStrategy implements CallbackStrategy {

    private static final Logger log = LoggerFactory.getLogger(AbstractCallbackStrategy.class);

    /**
     * accessor
     *
     * @return
     */
    protected abstract AbstractAccessor getAccessor();

    /**
     * 执行回调
     */
    @Override
    public Map<String, Object> executeCallback(String callbackUrl, CommonReq<List<Map<String, Object>>> commonReq) {

        Map map = new HashMap();
        try {
            map = getAccessor().defaultPostForValue(callbackUrl, commonReq, Map.class);
        } catch (Exception e) {
            map.put(CallbackConstants.CODE, CallbackConstants.ERROR_CODE);
            map.put(CallbackConstants.MSG, e.getMessage());
            log.error("服务调用异常,异常信息如下:{}", e);
        }
        return map;
    }
}

 第三步:定义feign调用回调策略类


import com.*.CallbackTypeEnum;
import com.*.utils.AbstractAccessor;
import com.*.FeignAccessor;
import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Component;

/**
 * @since 2023/7/18
 */
@Component
@RequiredArgsConstructor
public class FeignCallbackStrategy extends AbstractCallbackStrategy implements CallbackStrategy {

    private final FeignAccessor feignAccessor;

    @Override
    public String getSupportCallbackType() {
        return CallbackTypeEnum.FEIGN.getCode();
    }

    @Override
    protected AbstractAccessor getAccessor() {
        return feignAccessor;
    }
}

第四步:定义 http回调策略类

import com.*.CallbackTypeEnum;
import com.*.AbstractAccessor;
import com.*.HttpAccessor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * @since 2023/7/18
 */
@Component
@RequiredArgsConstructor
public class HttpCallbackStrategy extends AbstractCallbackStrategy implements CallbackStrategy {

    private final HttpAccessor httpAccessor;

    @Override
    public String getSupportCallbackType() {
        return CallbackTypeEnum.HTTP.getCode();
    }

    @Override
    protected AbstractAccessor getAccessor() {
        return httpAccessor;
    }
}

 

第五步:定义访问方式抽象类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

/**
 * @since 2023/7/18
 */
public abstract class AbstractAccessor {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractAccessor.class);

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse对象
     * 默认的数据请求格式为application/json
     * </pre>
     *
     * @param url   微服务地址
     * @param param 请求参数
     * @param clazz 返回类型
     */
    public <T> T defaultPostForValue(String url, Object param, Class<T> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        HttpEntity<?> entity = new HttpEntity<>(param, headers);
        return postForValue(url, entity, clazz);
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse对象
     * 默认的数据请求格式为application/json
     * </pre>
     *
     * @param url   微服务地址
     * @param param 请求参数
     * @param clazz 返回类型
     */
    public <T> ResponseEntity<T> defaultPostForEntity(String url, Object param, Class<T> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        HttpEntity<?> entity = new HttpEntity<>(param, headers);
        return postForEntity(url, entity, clazz);
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse后的Data值对象
     * </pre>
     *
     * @param url    微服务地址
     * @param entity 请求实体
     * @param clazz  返回类型
     */
    public <T, R> T postForValue(String url, HttpEntity<R> entity, Class<T> clazz) {
        ResponseEntity<T> responseEntity = this.postForEntity(url, entity, clazz);
        return responseEntity.getBody();
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse后的Data值对象
     * </pre>
     *
     * @param url    微服务地址
     * @param entity 请求实体
     * @param clazz  返回类型
     */
    public <T, R> ResponseEntity<T> postForEntity(String url, HttpEntity<R> entity, Class<T> clazz) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("远程地址:{},请求参数:{}", url, JSON.toJSONString(entity.getBody(),
                    SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames));
        }
        ResponseEntity<T> responseEntity = getRestTemplate().exchange(url, HttpMethod.POST, entity, clazz);
        if (LOG.isDebugEnabled()) {
            LOG.debug("远程地址:{},返回结果:{}", url, JSON.toJSONString(responseEntity.getBody(),
                    SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames));
        }
        return responseEntity;
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse对象
     * 默认的数据请求格式为application/json
     * </pre>
     *
     * @param url   微服务地址
     * @param param 请求参数
     * @param clazz 返回类型
     */
    public <T> T defaultGetForValue(String url, Object param, Class<T> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        HttpEntity<?> entity = new HttpEntity<>(param, headers);
        return getForValue(url, entity, clazz);
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse对象
     * 默认的数据请求格式为application/json
     * </pre>
     *
     * @param url   微服务地址
     * @param param 请求参数
     * @param clazz 返回类型
     */
    public <T> ResponseEntity<T> defaultGetForEntity(String url, Object param, Class<T> clazz) {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        HttpEntity<?> entity = new HttpEntity<>(param, headers);
        return getForEntity(url, entity, clazz);
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse后的Data值对象
     * </pre>
     *
     * @param url    微服务地址
     * @param entity 请求实体
     * @param clazz  返回类型
     */
    public <T, R> T getForValue(String url, HttpEntity<R> entity, Class<T> clazz) {
        ResponseEntity<T> responseEntity = this.getForEntity(url, entity, clazz);
        return responseEntity.getBody();
    }

    /**
     * <pre>
     * 远程调用微服务,返回ApiResponse后的Data值对象
     * </pre>
     *
     * @param url    微服务地址
     * @param entity 请求实体
     * @param clazz  返回类型
     */
    public <T, R> ResponseEntity<T> getForEntity(String url, HttpEntity<R> entity, Class<T> clazz) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("远程地址:{},请求参数:{}", url, JSON.toJSONString(entity.getBody(),
                    SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames));
        }
        ResponseEntity<T> responseEntity = getRestTemplate().exchange(url, HttpMethod.GET, entity, clazz);
        if (LOG.isDebugEnabled()) {
            LOG.debug("远程地址:{},返回结果:{}", url, JSON.toJSONString(responseEntity.getBody(),
                    SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames));
        }
        return responseEntity;
    }

    protected abstract RestTemplate getRestTemplate();
}

 第六步:定义feign调用方式


import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * @since 2023/7/18
 */
@Component
public class FeignAccessor extends AbstractAccessor {

    @Resource(name = "feignRestTemplate")
    private RestTemplate feignRestTemplate;

    @Override
    protected RestTemplate getRestTemplate() {
        return feignRestTemplate;
    }
}

 第七步:http调用方式


import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * @author huangdh
 * @since 2023/7/18
 */
@Component
public class HttpAccessor extends AbstractAccessor {

    @Resource(name = "httpRestTemplate")
    private RestTemplate httpRestTemplate;

    @Override
    protected RestTemplate getRestTemplate() {
        return httpRestTemplate;
    }
}

 

 第八步:接口回调

/**
 * @since 2023/7/17
 */
@Service
@RequiredArgsConstructor
public class CallbackAppServiceImpl implements CallbackAppService {

    private final List<CallbackStrategy> callbackStrategyList;

    /**
     * 回调明细操作
     *
     * @param batchId
     * @param serialNumber
     * @param interfaceCode
     */
    private boolean executeCallbackDetail(Long batchId, String serialNumber, String interfaceCode) {
       
            // 通过 interfaceCode 获取回调地址,并返回List<BaseCallbackConfigBO>
            BaseCallbackConfigBO callbackConfigBO = callbackConfigDomainService.getCallbackUrlByInterfaceCode(interfaceCode);
            String callbackType = callbackConfigBO.getCallbackType();
            String callbackUrl = callbackConfigBO.getCallbackServiceName();
            // 构造回调参数
            List<Map<String, Object>> maps = boList.stream().map(obj -> {
                Map<String, Object> map = new HashMap<>();
                map.put("callBackCode", obj.getProcessStatus());
                map.put("callBackMsg", obj.getProcessMessage());
                return map;
            }).collect(Collectors.toList());
            CommonReq<List<Map<String, Object>>> commonReq = CommonReq.build(maps);

            Map<String, Object> map = callbackStrategyList.stream().filter(obj -> callbackType.equals(obj.getSupportCallbackType())).findFirst().get().executeCallback(callbackUrl, commonReq);
            return true;
    }
}

 

标签:JAVA,url,param,clazz,return,模式,import,设计模式,public
From: https://www.cnblogs.com/huangdh/p/17757897.html

相关文章

  • JAVA图搜索算法之DFS-BFS
    图算法DFS与BFSBFS和DFS代表对图进行遍历,即搜索的算法,搜索算法中常用的只要有两种算法:深度优先遍历(Depth-First-Search:DFS)和广度优先遍历(Breadth-First-Search:BFS)。一个图结构可以用来表示大量现实生活中的问题,比如,道路网络,计算机网络,社交网络,用户身份解析图①DFS......
  • Java 导出Excel根据单元格内容计算并设置列宽度、行高
    话不多说,上代码:importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.ss.util.CellRangeAddress;importjava.util.HashMap;importjava.util.Map;importjava.util.Objects;/***根据单元格内容计算并设置列宽度、行高*/publicclassExcelUtil{//......
  • 1——of C++ and Java togather
    因为那个C++最全的笔记是从第18课开始做(笔者说18课之前都很基础),所以这里就对前18课的知识做个笔记总结C++的工作过程这里提到的C++工作过程主要涉及两个:编译与链接之前考研时候学到,(在组成原理的某个章节),计算机的工作过程其实就涉及“将源程序转换成可执行文件”,与其中便......
  • C++ - 单例模式实现
    1.什么是单例模式单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。为什么需要单例模式两个原因:节省资源。一个类只有一个实例,不存在多份实例,节省资源。方便控制。在一些操作公共资源的场景时,避免了多个对象引起的复杂操作。但是在实现单例......
  • 利用模式快速导入模板代码
    在ABAP编辑器中,模式不仅可以调用函数和方法,还可以用于多种ABAP操作和语言构造,包括您自己的模式定义。定义自己的模式可以定义自己的模式快速插入统一的备注,模板代码等重复使用内容。在ABAP工作台中,选择菜单路径,实用程序>更多实用程序>编辑模式>创建模式,可以创建模式。模式的内容存......
  • java 后台防止重复提交(注解方式)
    /***自定义注解防止表单重复提交**@authorframework*/@Inherited@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceRepeatSubmit{/***间隔时间(ms),小于此时间视为重复提交*/intinterval(......
  • java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a M
    原文链接:https://www.longkui.site/error/java-lang-illegalargumentexception-expected-multiparthttpservletrequest-is-a-multipartresolver-configured/4837/0.背景JAVA后台一个上传excel的接口,如下:importData(@RequestParam("file")MultipartFilefile)然后,前台按......
  • Java程序【生产问题】排查
    1.查看线程数:方法一:查看/proc/[进程ID]/grepThreads/proc/[进程ID]/status方法二:ps-L-opid,tid,comm,state-p[进程ID]2.jstack分析Java堆栈jstack-l[进程ID]3.查看IOeg:如果有toomanyopenfiles的报错,则说明程序打开的文件过多1.查看该进程打开......
  • JavaScript :全局对象
    全局对象是一个常规的JavaScript对象,具有非常重要的用途:该对象的属性是全局定义的标识符,可供JavaScript解释器启动(或每当Web浏览器加载新页面时)使用,它会创建一个新的全局对象对象并为其提供一组初始属性,这些属性定义:全局常量,例如undefined、infinity和NaN。全局函数,如isN......
  • JavaScript之正则表达式
    正则表达式(RegExp)正则表达式不是JS独有的内容,大部分语言都支持正则表达式JS中正则表达式使用得不是那么多,我们可以尽量避免使用正则表达式在JS中,正则表达式就是RegExp对象,RegExp对象用于将文本与一个模式匹配正则表达式(regularexpressions,规则表达式)正则表达式用来定......