JAVA设计模式-策略模式
什么是策略模式
策略模式(Strategy Pattern) 也叫 政策模式(Policy Pattern)。指的是对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。
策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。
策略模式本质:分离算法,选择实现
场景
· 针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
优缺点
优点
· 有效避免多重条件判断,增强了封装性,简化了操作,降低出错概率;
· 扩展性良好,策略类遵顼 里氏替换原则,可以很方便地进行策略扩展;
缺点
· 策略类数量增多,且所有策略类都必须对外暴露,以便客户端能进行选择;
模式讲解
基础用法
大家都知道商城经常会有优惠活动,但是优惠策略会有多种可能。比如:领取优惠券、返现促销、拼团优惠等。
抽象类
public interface IPromotionStrategy { void doPromotion(); }
实现类
然后分别创建优惠券抵扣策略、返现促销策略、拼团优惠策略及无优惠策略。
public class CouponStrategy implements IPromotionStrategy { public void doPromotion() { System.out.println("使用优惠券抵扣"); } } public class CashbackStrategy implements IPromotionStrategy { public void doPromotion() { System.out.println("返现,直接打款到支付宝账号"); } } public class GroupbuyStrategy implements IPromotionStrategy { public void doPromotion() { System.out.println("5人成团,可以优惠"); } } public class EmptyStrategy implements IPromotionStrategy { public void doPromotion() { System.out.println("无优惠"); } }
public class PromotionActivity { private IPromotionStrategy strategy; public PromotionActivity(IPromotionStrategy strategy) { this.strategy = strategy; } public void execute(){ strategy.doPromotion(); } }
策略模式在云巧中的应用
在 4A 组件的 SDK 中,通过策略模式实现了支持多种登录方式
定义登录的关键接口
public interface IClientForSession { /** * 根据 token 获取用户信息 * @param accessToken * @return */ ReturnT<UserInfo> describeUserSessionInfo(String accessToken); /** * 销毁 session 会话 * @param sessionId * @return */ ReturnT invalidSessionId(String sessionId); }
通过实现关键接口对接不同的用户中心
对接 CAS
public class IClientForSessionImpl implements IClientForSession { private static final String SSO_SESSIONID = "xxl_sso_sessionid"; private static CloseableHttpClient httpClient; @Autowired SsoParameter ssoParameter; static { httpClient = HttpClientBuilder.create().build(); } @Override public ReturnT<UserInfo> describeUserSessionInfo(String accessToken) { Map<String, String> params = new HashMap<>(); params.put("cacheKey", cacheKey(accessToken)); String result = doPost(ssoParameter.getLoginServerUrlInternal(), "sso-server/usercenter/sysCache/cacheValAqusitionByCacheKey", params); if (result != null) { BaseResult<SysCacheResVO> baseResult = JSONObject.parseObject(result, new TypeReference<BaseResult<SysCacheResVO>>(){}); Object objectValue = null; if(!ObjectUtils.isEmpty(result) && !ObjectUtils.isEmpty(baseResult.getData())){ SysCacheResVO sysCacheResVO = JSON.parseObject(JSON.toJSONString(baseResult.getData()), SysCacheResVO.class); objectValue = sysCacheResVO.getCacheValueObj(); } if (objectValue != null) { XxlSsoUserVo xxlUser = JSON.parseObject(JSON.toJSONString(objectValue), XxlSsoUserVo.class); //todo 登录时间校验 if (xxlUser != null) { UserInfo userInfo = new UserInfo(); userInfo.setSessionId(accessToken); BaseUserInfo baseUserInfo = new BaseUserInfo(); baseUserInfo.setUserId(xxlUser.getUserid()); baseUserInfo.setUserName(xxlUser.getUsername()); userInfo.setBaseInfo(baseUserInfo); ReturnT<UserInfo> res = new ReturnT<UserInfo>(); res.setData(userInfo); return res; } } } return null; } @Override public ReturnT invalidSessionId(String sessionId) { return ReturnT.SUCCESS; } private String doPost(String ssoServerUrl, String action, Map<String, String> params) { String url = ssoServerUrl + "/" + action; HttpPost post = new HttpPost(url); post.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE); // List<NameValuePair> pairs = new ArrayList<NameValuePair>(); if (params != null) { // for (Map.Entry<String, String> entry : params.entrySet()) { // pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); // } try { try { post.setEntity(new StringEntity(JSON.toJSONString(params), "UTF-8")); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { } } // 响应模型 CloseableHttpResponse response = null; String result = null; try { // 由客户端执行(发送)Get请求 response = httpClient.execute(post); // 从响应模型中获取响应实体 HttpEntity responseEntity = response.getEntity(); if (responseEntity != null) { result = EntityUtils.toString(responseEntity); } } catch (Exception e) { } finally { if (response != null) { try { response.close(); } catch (IOException e) { } } } return result; }
对接 IDaaS
public class IClientForSessionImpl implements IClientForSession { @Autowired HttpServletRequest request; @Autowired SsoParameter ssoParameter; @Value("${idaas.client.id}") private String clientId; @Value("${idaas.client.secret}") private String clientSecret; @Override public ReturnT<UserInfo> describeUserSessionInfo(String accessToken) { Map<String, String> params = new HashMap<>(); params.put(ssoParameter.getAccessTokenKey(), accessToken); params.put("grant_type", "authorization_code"); params.put("client_id", clientId); params.put("client_secret", clientSecret); String ssoServerUrl = ssoParameter.getFouraServiceUrl() + "/oauth/token" + "?" + ssoParameter.getAccessTokenKey() + "=" + accessToken + "&grant_type=authorization_code" + "&client_id=" + clientId + "&client_secret=" + clientSecret + "&redirect_uri=" + URLEncoder.encode(SsoUtil.getCallerHost(request) + ssoParameter.getLoginPath()); String result = HttpUtil.doPost(ssoServerUrl, null, null); if (result != null) { String userAccessToken = JSON.parseObject(result).getString("access_token"); String describeUserUrl = ssoParameter.getFouraServiceUrl() + "/api/bff/v1.2/oauth2/userinfo?access_token=" + userAccessToken; String userResult = HttpUtil.doGet(describeUserUrl); if (userResult != null) { JSONObject userMap = JSON.parseObject(userResult).getJSONObject("data"); BaseUserInfo baseUserInfo = new BaseUserInfo(); baseUserInfo.setUserId(userMap.getString("sub")); baseUserInfo.setUserCode((String)userMap.getString("sub")); baseUserInfo.setUserName((String)userMap.getString("nickname")); OrgInfo orgInfo = new OrgInfo(); orgInfo.setId(1L); orgInfo.setOrgId(userMap.getString("ou_id")); orgInfo.setOrgName(userMap.getString("ou_name")); List<OrgInfo> orgList = new ArrayList(); orgList.add(orgInfo); UserInfo userInfo = new UserInfo(); userInfo.setBaseInfo(baseUserInfo); userInfo.setOrgInfoList(orgList); userInfo.setSessionId(userAccessToken); ReturnT<UserInfo> res = new ReturnT<UserInfo>(); res.setData(userInfo); return res; } } return null; } @Override public ReturnT invalidSessionId(String sessionId) { return ReturnT.SUCCESS; } }