装饰器强调的是动态功能增强,而这种增强是比单继承更加的灵活的方式,可以动态的给基类扩展不同的功能。
继承实现增强有不同结构
如果是按照最小原则,是这样的⬇︎⬇︎⬇︎
如果不想那么多类文件,是这样的⬇︎⬇︎⬇︎
虽然这样都能实现让子类拥有base/A/B三个操作,但如果现在只需要base/B操作怎么办。差的是灵活性,强调是动态。
可增可撤的增强功能
AccessToken⬇︎⬇︎⬇︎
点击查看代码
package com.xxx.sales.saicorder.outerapp;
/**
* accessToken 是最接近访问接口的动态令牌,拿到此令牌即可调用需要授权的接口
* 注意:在标准的授权登录中,是要先拿到用户授权的code,然后携code取accessToken信息
* T : 表示获取code的参数,通常是app_key和secret
* V : 表示用户授权,开放平台返回的结构
* Z : 表示获取令牌,开放平台返回的结构
*
* @author Euler
*/
public interface AccessToken<T, V, Z> {
/**
* 获取授权码
* <p>
* 用户授权后,开放平台返回的code。一般通过redirect方式返回
*
* @param params
* @return
*/
V getCode(T params);
/**
* 获取访问令牌
* <p>
* 通过code获取对应的accessToken
*
* @param codeResponse 授权码响应结果
* @return
*/
Z getAccessToken(V codeResponse);
}
BaseAccessToken ⬇︎⬇︎⬇︎
点击查看代码
package com.xxx.sales.saicorder.outerapp.tmall.accesstoken;
import com.xxx.sales.saicorder.outerapp.AccessToken;
import com.xxx.sales.saicorder.outerapp.tmall.req.CodeRequest;
import com.xxx.sales.saicorder.outerapp.tmall.resp.AccessTokenResponse;
import com.xxx.sales.saicorder.outerapp.tmall.resp.CodeResponse;
/**
* 通过阿里开放平台的接口,获取数据
*
* @author Euler
*/
public class BaseAccessToken implements AccessToken<CodeRequest, CodeResponse, AccessTokenResponse> {
/**
* 获取授权码
* <p>
* 用户授权后,开放平台返回的code。一般通过redirect方式返回
*
* @param params
* @return
*/
@Override
public CodeResponse getCode(CodeRequest params) {
return null;
}
/**
* 获取访问令牌
* <p>
* 通过code获取对应的accessToken
*
* @param codeResponse 授权码响应结果
* @return
*/
@Override
public AccessTokenResponse getAccessToken(CodeResponse codeResponse) {
return null;
}
}
CacheWrapperAccessToken⬇︎⬇︎⬇︎
点击查看代码
package com.xxx.sales.saicorder.outerapp.tmall.accesstoken;
import com.xxx.sales.saicorder.outerapp.AccessToken;
import com.xxx.sales.saicorder.outerapp.tmall.req.CodeRequest;
import com.xxx.sales.saicorder.outerapp.tmall.resp.AccessTokenResponse;
import com.xxx.sales.saicorder.outerapp.tmall.resp.CodeResponse;
/**
* 基于缓存的accessToken的实现
* <p>
* 如果多个系统共同使用一个accessToken,可以将其通过redis共享。
* 默认实现是基于进程内的内存共享
*
* @author Euler
*/
public class CacheWrapperAccessToken implements AccessToken<CodeRequest, CodeResponse, AccessTokenResponse> {
/**
* 基于请求天猫接口的实现
*/
private AccessToken accessToken;
public CacheWrapperAccessToken(AccessToken accessToken) {
this.accessToken = accessToken;
}
/**
* 获取授权码
* <p>
* 用户授权后,开放平台返回的code。一般通过redirect方式返回
*
* @param params
* @return
*/
@Override
public CodeResponse getCode(CodeRequest params) {
//先从缓存取,缓存没有在从取源数据
return null;
}
/**
* 获取访问令牌
* <p>
* 通过code获取对应的accessToken
*
* @param codeResponse 授权码响应结果
* @return
*/
@Override
public AccessTokenResponse getAccessToken(CodeResponse codeResponse) {
//先从缓存取,缓存没有在从取源数据
return null;
}
}
mybatis的执行器也是这样的
点击查看代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.ibatis.executor;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.cache.TransactionalCacheManager;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.mapping.StatementType;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.Transaction;
public class CachingExecutor implements Executor {
private final Executor delegate;
private final TransactionalCacheManager tcm = new TransactionalCacheManager();
public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}
public Transaction getTransaction() {
return this.delegate.getTransaction();
}
public void close(boolean forceRollback) {
try {
if (forceRollback) {
this.tcm.rollback();
} else {
this.tcm.commit();
}
} finally {
this.delegate.close(forceRollback);
}
}
public boolean isClosed() {
return this.delegate.isClosed();
}
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
this.flushCacheIfRequired(ms);
return this.delegate.update(ms, parameterObject);
}
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
this.flushCacheIfRequired(ms);
return this.delegate.queryCursor(ms, parameter, rowBounds);
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
this.flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
this.ensureNoOutParams(ms, boundSql);
List<E> list = (List)this.tcm.getObject(cache, key);
if (list == null) {
list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
this.tcm.putObject(cache, key, list);
}
return list;
}
}
return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public List<BatchResult> flushStatements() throws SQLException {
return this.delegate.flushStatements();
}
public void commit(boolean required) throws SQLException {
this.delegate.commit(required);
this.tcm.commit();
}
public void rollback(boolean required) throws SQLException {
try {
this.delegate.rollback(required);
} finally {
if (required) {
this.tcm.rollback();
}
}
}
private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
Iterator var3 = boundSql.getParameterMappings().iterator();
while(var3.hasNext()) {
ParameterMapping parameterMapping = (ParameterMapping)var3.next();
if (parameterMapping.getMode() != ParameterMode.IN) {
throw new ExecutorException("Caching stored procedures with OUT params is not supported. Please configure useCache=false in " + ms.getId() + " statement.");
}
}
}
}
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
return this.delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}
public boolean isCached(MappedStatement ms, CacheKey key) {
return this.delegate.isCached(ms, key);
}
public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
this.delegate.deferLoad(ms, resultObject, property, key, targetType);
}
public void clearLocalCache() {
this.delegate.clearLocalCache();
}
private void flushCacheIfRequired(MappedStatement ms) {
Cache cache = ms.getCache();
if (cache != null && ms.isFlushCacheRequired()) {
this.tcm.clear(cache);
}
}
public void setExecutorWrapper(Executor executor) {
throw new UnsupportedOperationException("This method should not be called");
}
}
下面是代理↡↡↡↡
代理侧重于控制对真实对象的访问
标签:return,代理,模式,VS,delegate,ms,apache,import,public From: https://www.cnblogs.com/euler-blog/p/18613419比如,使用nginx进行反向代理最能体现这一思想。但在代码中使用代理更多的是功能增强,功能增强是代理模式的附加属性。