java策略模式,在我的认知中是根据不同选择执行不同的实现。通过if或者switch-case也能实现这种逻辑,但是代码冗余,可扩展性不强。
百度百科上的解释为策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
这里我只是分享一下我在接收微信事件推送上使用策略模式的方法。接触过微信开发的都清楚,微信所有的事件推送只能推送到我们填写的那个接口,我们需要不同的事件执行不同的逻辑。这个时候策略模式都优势就展现出来了。
以下是具体实现:
2接收到的参数一般都是xml格式的我们先将xml解析成map。(工程需引入 org.dom4j 2.1.1)
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* XML解析
*/
public class XmlConvert {
/*
* XML转map
*/
public static Map xmlToMap(InputStream ins) {
HashMap map = null;
try {
map = new HashMap();
SAXReader reader = new SAXReader();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List list = (List) root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
ins.close();
} catch (DocumentException |IOException e) {
e.printStackTrace();
}
return map;
}
}
3定义事件处理接口与方法
目录结构
3.1定义策略接口
import java.util.Map;
/**
* 微信事件处理接口 策略模式
*/
public interface ICallBackService {
/**
* 响应事件
* @return
*/
public Map Event(Map eventMap);
}
3.2 定义策略接口的实现,选择几个常用的微信事件做样例
import 自己的包路径.ICallBackService;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 点击按钮事件
*/
@Service
public class Click implements ICallBackService {
@Override
public Map Event(Map eventMap) {
System.out.println("Click");
return null;
}
}
import 自己的包路径.ICallBackService;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 关注事件
*/
@Service
public class Subscribe implements ICallBackService {
@Override
public Map Event(Map eventMap) {
System.out.println("Subscribe");
return null;
}
}
import 自己的包路径.ICallBackService;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 取消关注事件
*/
@Service
public class Unsubscribe implements ICallBackService {
@Override
public Map Event(Map eventMap) {
System.out.println("Unsubscribe");
return null;
}
}
import 自己的包路径.ICallBackService;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 点击视图菜单事件
*/
@Service
public class View implements ICallBackService {
@Override
public Map Event(Map eventMap) {
System.out.println("View");
return null;
}
}
4根据微信推送事件类型选择具体实现
import 自己的包路径.ICallBackService; // 事件接口
import 自己的包路径.XmlConvert; // xml转map
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* 接收微信事件推送接口
* get 和 post 方法访问路径一定要一致。
*/
@RestController
@RequestMapping("weixinCallBack")
public class WeiXinCallbackController {
@Autowired
private List callBackServices; //以集合的方式自动注入接口
/**
* 接收消息推送
* 一定要使用【post】方式
*
* @param request
* @param resp
* @return
*/
@PostMapping(value = "/callBack")
public Boolean callBack(HttpServletRequest request, HttpServletResponse resp) {
try {
// 将输入xml流转换为Map方便取值
Map dataMap = XmlConvert.xmlToMap(request.getInputStream());
for (ICallBackService callBackService : callBackServices) {
// 更具事件名称使用事件接口的具体实现
// Event 是微信的事件类型,事件类型与我们的接口实现名称一致,判断都统一转成大写
if (callBackService.getClass().getSimpleName().toUpperCase().equals(dataMap.get("Event").toUpperCase())) {
// 执行事件方法
callBackService.Event(dataMap);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 返回给微信,如果没有返回微信会重试几次
return true;
}
}
在本地实际操作输出以下内容
至此通过策略模式在接收微信公众号事件推送上的具体运用就结束了。具体的每种事件的逻辑可以在自己的实现层去完成,通过策略模式扩展了代码的可维护性,添加新的事件也不用去控制层添加东西。
策略模式在各个地方说的都比较多,但是实际的使用一般说的比较少。重点是策略模式的理解,难点在于策略模式的具体实现与具体运用。
欢迎大家一起交流IT技术 2742389525@qq.com 一个2015年入坑的无聊的java工程师