首页 > 其他分享 >《装饰器模式》VS《代理模式》

《装饰器模式》VS《代理模式》

时间:2024-12-17 21:09:52浏览次数:6  
标签:return 代理 模式 VS delegate ms apache import public

装饰器强调的是动态功能增强,而这种增强是比单继承更加的灵活的方式,可以动态的给基类扩展不同的功能。

继承实现增强有不同结构

如果是按照最小原则,是这样的⬇︎⬇︎⬇︎
image

如果不想那么多类文件,是这样的⬇︎⬇︎⬇︎
image

虽然这样都能实现让子类拥有base/A/B三个操作,但如果现在只需要base/B操作怎么办。差的是灵活性,强调是动态。

可增可撤的增强功能

image
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的执行器也是这样的

image

点击查看代码
//
// 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");
    }
}


下面是代理↡↡↡↡

代理侧重于控制对真实对象的访问

比如,使用nginx进行反向代理最能体现这一思想。但在代码中使用代理更多的是功能增强,功能增强是代理模式的附加属性。

标签:return,代理,模式,VS,delegate,ms,apache,import,public
From: https://www.cnblogs.com/euler-blog/p/18613419

相关文章

  • 《单例模式》我只用这一种
    双重检查是我用的最多的一种。因为它是一种线程安全的写法,而这种写法可以应用到各种场景中。比如:涉及到多线程共享的数据,在更新时候的使用。比如这种:其他的方式也有,比如内部类的实现方式。点击查看代码publicclassSingletonEagerInnerClass{privateSingletonEage......
  • Redis篇之Redis高可用模式参数调优,提高Redis性能
    1.Redis高可用模式核心Redis高可用模式的核心是使用主从复制和自动故障转移机制来确保系统在某些节点发生故障时仍然可以正常工作。常用的高可用架构包括RedisSentinel模式和RedisCluster模式,其中Sentinel模式是为了提供高可用性而专门设计的解决方案。在RedisSent......
  • 都在使用的《模版模式》
    模版符合开闭原则,到处用于钩子方法。有的钩子方法不会改变行为,有的钩子会改变运行轨迹。框架中到处使用。Channel中定义了需要的操作,AbstractChannel实现了核心功能,然后不同的Channel实现只需要告知具体channel的描述信息即可。Channel接口⬇︎⬇︎⬇︎点击查看代码packagecom.x......
  • 【YashanDB知识库】如何处理yasql输入交互模式下单行字符总量超过限制4000字节
    现象在yasql执行sql语句后报错:YASQL-00021inputlineoverflow(>4000byteatline4)原因yasql在交互模式模式下单行字符总量限制4000字节,超出该限制即报错。交互式模式下,yasql会显示一个提示符,通常是SQL>,等待用户输入命令,用户执行的每个命令都会立即执行,并显示结果。......
  • 【YashanDB知识库】用yasldr配置Bulkload模式作单线程迁移300G的业务数据到分布式数据
    问题描述详细版本:YashanDBServerEnterpriseEditionRelease23.2.4.100x86_646db1237影响范围:离线数据迁移场景,影响业务数据入库。外场将部分NewCIS的报表业务放到分布式数据库,验证SQL性能水平。操作系统环境配置:125G内存32CCPU2T的HDD磁盘问题出现的步骤/操作:1、......
  • 大家都一样的《策略模式》
    不同类型的消息处理这里抽象层用的是接口MessageProcess⬇︎⬇︎⬇︎点击查看代码/***消息处理**@authorhaiyang*/publicinterfaceMessageProcess<K,V>{/***处理消息**@parammessageInfo消息相关信息*@return{@linkV}......
  • 不同操作系统中安装Visual Studio Code(以下简称VS Code)的详细步骤
    Windows系统下载安装包打开浏览器,访问VSCode官方网站(https://code.visualstudio.com/)。在官网首页找到“DownloadforWindows”按钮并点击,下载安装程序(.exe文件)。运行安装程序下载完成后,找到安装程序文件并双击运行它。在安装向导中,你可以选择安装路径。默认路径是“......
  • workman服务端开发模式-应用开发-websockt应用配置
    一、配置文件开发    在根目录下创建conf.ini文件并写入一下代码:[redis]host=172.30.7.95port=6379password=QXtr@@PxjoLenGontoken1=123token2=121[socket]register_host=172.30.7.95register_port=1239register_name=SocketBusinessWorkergateway_host=......
  • VS code轻量级开发平台配置(C/C++版)
    写c++代码一直用VS,后来发现太麻烦了,转站vs code。按照步骤安装,问题不大。我也是跟着一个博主学习安装的,一起学习。一、VS code下载下载链接:DownloadVisualStudioCode-Mac,Linux,Windows对应选择适合自己电脑的版本,安装路径自定义时不要包含中文字符,其他的直接下一......
  • 什么是多租户,多租户的模式、多租户的优点、多租户的挑战和解决方案
    多租户的定义多租户(Multi-Tenancy)是一种软件架构技术,它使得单个软件实例能够为多个不同的用户组(即租户)提供服务。这些租户在使用软件系统时,感觉就像是在使用自己独占的系统,但实际上他们共享软件的基础设施、数据库、服务器等资源。例如,在一个基于云的企业资源规划(ERP)系统中,多......