当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。观察者模式属于行为型模式。
示例
观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。
观察着模式在平常开发中,有可能各位博友有引用到,只是自己没发现而已,博主在这就以项目实例来进行说明。
场景介绍:
微信公众号开发,获取接口调用凭证AccessToken,AccessToken的expires_in凭证有效时间(expires_in-当前时间>0),此时需要对AccessToken入库,AccessToken失效重新获取并更新数据库(AccessToken入库一般在服务器对于多公众号支持时)。
第一步定义Subject
清除的知道Subject的作用:Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法
WxConfig微信基本参数配置类,需单例
package com.bigbigbu.wx.tools.api;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.bigbigbu.wx.tools.bean.WxAccessToken;
import com.bigbigbu.wx.tools.exception.WxErrorException;
import com.bigbigbu.wx.tools.util.StringUtils;
/**
* <p>Title: WxAccessToken</p>
* <p>Description: 微信全局配置对象-从配置文件读取,原作者antgan于2016/12/14码</p>
* <p>Company: BIGBIGBU</p>
* @author FANQIBU
* @date 2017年12月7日
*/
public class WxConfig {
private static WxConfig config = null;
//内存更新
private volatile String accessToken;
private volatile long expiresTime;
//多公众号模式下自定义系统回调===========重点==观察者模式=============
private IWxManySysService wxManySysService;
/**
* @Title: WxConfig
* @Description: FANQIBU 动态加载配置文件
* @param:
* @throws
*/
public WxConfig() {
}
/**
* 同步获取/加载单例
* @return
*/
public static synchronized WxConfig getInstance(){
if(config == null){
config = new WxConfig();
}
return config;
}
/**
* 同步获取/加载单例
* @return
*/
public static synchronized void refreshInstance(){
config = new WxConfig();
}
public String getAccessToken() {
return accessToken;
}
public boolean isAccessTokenExpired() {
return System.currentTimeMillis() > this.expiresTime;
}
public void expireAccessToken() {
this.expiresTime = 0;
}
/**
* <p>Title: updateAccessToken</p>
* <p>Description: 更新接口调用凭证</p>
* @param WxAccessToken accessToken
* @param boolean isCallback 是否调用系统回调
*/
public synchronized void updateAccessToken(WxAccessToken accessToken,boolean isCallback) {
updateAccessToken(accessToken.getAccess_token(), accessToken.getExpires_in(),isCallback);
}
/**
* <p>Title: updateAccessToken</p>
* <p>Description: FANQIBU修改更新接口调用凭证</p>
* @param String accessToken
* @param long expiresInSeconds
* @param boolean isCallback 是否调用系统回调
*/
public synchronized void updateAccessToken(String accessToken, long expiresInSeconds,boolean isCallback) {
this.accessToken = accessToken;
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
//调用微信WxSysCallback
if(this.getWxManySysService()!=null && isCallback){
//微信刷新access_token接口调用凭证回调(PS:针对多公众号情况下access_token更新入库操作)(在这里了)
//通知更新access_token啦。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
this.getWxManySysService().wxAccessTokenCallback(this.accessToken, this.expiresTime);
}
}
public IWxManySysService getWxManySysService() {
return wxManySysService;
}
public void setWxManySysService(IWxManySysService wxManySysService) {
this.wxManySysService = wxManySysService;
}
}
第二步定义Observer
/**
* <p>Title: IWxManySysService</p>
* <p>Description: 多公众号模式下动态加载配置信息和接口调用凭证access_token更新</p>
* <p>Company: DINGGE</p>
* @author FANQIBU
* @date 2017年12月7日
*/
public interface IWxManySysService {
/**
* <p>Title: wxAccessTokenCallback</p>
* <p>Description: 微信刷新access_token接口调用凭证回调(PS:一般针对多公众号情况下access_token更新入库操作)</p>
* @param accessToken
* @param expiresInSeconds
*/
public void wxAccessTokenCallback(String accessToken, long expiresInSeconds);
/**
* <p>Title: loadWxProperties</p>
* <p>Description:多公众号动态加载微信配置参数 </p>
* @param String wxsystoken 本地系统wx令牌(从数据库查找当前公众号配置参数)
*/
public default boolean loadWxProperties(String newwxsystoken){
if(StringUtils.isEmpty(newwxsystoken)){
return false;
}
try {
//WxConfig微信基本参数配置类,需单例
WxConfig.refreshInstance();
//=============绑定观察者=======重点在这里==================
WxConfig.getInstance().setWxManySysService(this);
}else{
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
package com.lh.wx.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import com.lh.wx.dao.WeixinAccessTokenMapper;
import com.lh.wx.dao.WeixinConfigMapper;
import com.lh.wx.model.WeixinAccessTokenDto;
import com.lh.wx.servlet.InitServlet;
import com.bigbigbu.wx.tools.api.IWxManySysService;
import com.bigbigbu.wx.tools.bean.WxAccessToken;
import com.bigbigbu.wx.tools.bean.many.WxBaseConfig;
/**
* <p>Title: WxSysCallback</p>
* <p>Description: 自定义系统回调</p>
* <p>Company: DINGGE</p>
* @author FANQIBU
* @date 2017年12月7日
*/
@Service
public class WxManySysService implements IWxManySysService{
private @Inject WeixinConfigMapper weixinConfigMapper;
private @Inject WeixinAccessTokenMapper weixinAccessTokenMapper;
private @Inject Environment environment;
@Override
public void wxAccessTokenCallback(String accessToken, long expiresInSeconds) {
//会通知这里
//更新数据库AccessToken
}
}
第三步简单使用
package com.lh.wx.service;
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service
public class WechatService {
private @Inject Environment environment;
private @Inject WxManySysService wxManySysService;
public boolean loadWxSysConfigure(String wxsystoken,boolean isMust){
//调用绑定观察者
wxManySysService.loadWxProperties(wxsystoken,environment.getProperty("wx.wxsystoken"));
}
}
本文博主只是在简单一对一条件下,使用观察者模式模式实现回调。详细请参阅菜鸟教程,本文头部介绍均引用自菜鸟教程