如何在Java中实现扩展性的几种策略和技巧

发表时间: 2023-11-21 12:16

点击链接阅读原文,获取更多技术内容:一文聊聊代码的可读性-阿里云开发者社区


在日常的开发中,作者总结了平常用到的一些低成本、保持扩展性的套路,分享出来,欢迎大家讨论。

作者 | 高止

来源 | 阿里云开发者公众号


前言

SOLID(单一、开闭、里式替换、接口隔离、依赖倒置)五大原则和23种设计模式(常见的单例、构建者、装饰、适配、代理、组合、模板等等),小伙伴们对这些肯定都很熟悉。这些原则和设计模式能够辅助我们,让我们在设计的时候有所抉择,从而达到高内聚、低耦合的目的。

那说到设计,肯定会提到架构两个字,常见的架构名词:分层架构、六边形架构、SOA架构、CQRS架构、EDA架构等等。我个人对架构的理解是边界的确认以及边界内部元素的组合,其实只要是程序员,他就一定是架构师,只不过是好的架构师还是不那么好的架构师;人人都是架构师,我认为这句话是没有问题的,区别在于他的认知决定了他所能确认的边界、如何更高效的组合内部元素;技术的架构师肯定侧重于技术,业务的架构师肯定侧重于业务,商品的架构师所能看到的边界大概率还是局限在商品域,ICBU架构组的架构师更多考虑是横向的业务支撑。以上是我个人对架构两个字的理解,今天我们不讨论具体架构,我们讨论一些套路,在日常的开发中,我总结了些我平常用到的一些低成本、保持扩展性的套路,分享出来,欢迎大家讨论。


基于管道(pipeline)的套路

关键点

  • 管道(Pipeline)----用于串联阀门的管道通路
  • 阀门(PipelineValue)----用于每一个节点处理实际业务诉求
  • 管道上下文(PipelineContext)----用于管道上下文中数据的扭转

适用场景

  • 当你的数据流需要经过很多同等逻辑处理时,可以考虑使用此套路,便于后续扩展

实现代码

  • Pipeline/StandardPipeline
package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:46 */public interface Pipeline {    /**     * 执行     *     * @return     */    boolean invoke(PipelineContext pipelineContext);    /**     * 添加值     *     * @param pipelineValue     * @return     */    boolean addValue(PipelineValue pipelineValue);    /**     * 移除值     *     * @param pipelineValue     * @return     */    boolean removeValue(PipelineValue pipelineValue);}package com.example.ownertest.dm.pipelline;import java.util.List;import com.google.common.collect.Lists;import lombok.Data;import lombok.extern.slf4j.Slf4j;/** * @Author: linear.zw * @Date: 2023/10/25 19:46 */@Data@Slf4jpublic class StandardPipeline implements Pipeline {    private List<PipelineValue> pipelineValueList = Lists.newArrayList();    @Override    public boolean invoke(PipelineContext pipelineContext) {        boolean isResult = true;        for (PipelineValue pipelineValue :            pipelineValueList) {            try {                isResult = pipelineValue.execute(pipelineContext);                if (!isResult) {                    log.error("{},exec is wrong", pipelineValue.getClass().getSimpleName());                }            } catch (Exception e) {                log.error(e.getMessage(), e);            }        }        return isResult;    }    @Override    public boolean addValue(PipelineValue pipelineValue) {        if (pipelineValueList.contains(pipelineValue)) {            return true;        }        return pipelineValueList.add(pipelineValue);    }    @Override    public boolean removeValue(PipelineValue pipelineValue) {        return pipelineValueList.remove(pipelineValue);    }}
  • PipelineContext/StandardPipelineContext
package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:47 */public interface PipelineContext {    String FOR_TEST = "forTest";    /**     * 设置     *     * @param contextKey     * @param contextValue     */    void set(String contextKey, Object contextValue);    /**     * 获取值     *     * @param contextKey     * @return     */    Object get(String contextKey);}package com.example.ownertest.dm.pipelline;import java.util.Map;import com.google.common.collect.Maps;/** * @Author: linear.zw * @Date: 2023/10/25 19:47 */public class StandardPipelineContext implements PipelineContext {    private Map<String, Object> contentMap = Maps.newConcurrentMap();    @Override    public void set(String contextKey, Object contextValue) {        contentMap.put(contextKey, contextValue);    }    @Override    public Object get(String contextKey) {        return contentMap.get(contextKey);    }}
  • PipelineValue/AbstractPipelineValue/GraySwitchValue/ForTestValue
package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:47 */public interface PipelineValue {    /**     * 节点执行     *     * @param pipelineContext     * @return     */    boolean execute(PipelineContext pipelineContext);}package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:48 */public abstract class AbstractPipelineValue implements PipelineValue {    @Override    public boolean execute(PipelineContext pipelineContext) {        System.out.println(this.getClass().getSimpleName() + " start ");        boolean result = doExec(pipelineContext);        System.out.println(this.getClass().getSimpleName() + " end ");        return result;    }    protected abstract boolean doExec(PipelineContext pipelineContext);}package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:48 */public class GraySwitchValue extends AbstractPipelineValue {    @Override    public boolean doExec(PipelineContext pipelineContext) {        pipelineContext.set(PipelineContext.FOR_TEST, true);        return true;    }}package com.example.ownertest.dm.pipelline;/** * @Author: linear.zw * @Date: 2023/10/25 19:48 */public class ForTestValue extends AbstractPipelineValue {    @Override    public boolean doExec(PipelineContext pipelineContext) {        return true;    }}
  • PipelineClient
package com.example.ownertest.dm.pipelline;/** * 入口类 * * @Author: linear.zw * @Date: 2023/10/25 19:48 */public class PipelineClient {    public static void main(String[] args) {        // 管道初始化        Pipeline pipeline = new StandardPipeline();        // value扩展        PipelineValue pipelineValue = new GraySwitchValue();        PipelineValue pipelineValue2 = new ForTestValue();        // 上下文        PipelineContext pipelineContext = new StandardPipelineContext();        pipeline.addValue(pipelineValue);        pipeline.addValue(pipelineValue2);        // 调用管道        pipeline.invoke(pipelineContext);    }}

常见框架中的应用

  • 网络层的扛把子netty框架中,例如ChannelPipeline、ChannelHandler、ChannelHandlerContext,分别用于处理tcp拆包、加解码等等之类。


基于责任链(filterchain)的套路

关键点


来源--https://www.oracle.com/java/technologies/intercepting-filter.html

  • 过滤器(Filter)----实际处理业务的节点
  • 过滤链(FilterChain)----串联过滤器的链条

适用场景

  • 例如常见的web请求场景

实现代码

  • Filter/ForTest1Filter/ForTest2Filter
package com.example.ownertest.dm.filter;/** * @Author: linear.zw * @Date: 2023/10/26 19:22 */public interface Filter {    void doFilter(HttpRequest httpRequest,FilterChain filterChain);}package com.example.ownertest.dm.filter;/** * @Author: linear.zw * @Date: 2023/10/26 19:22 */public class ForTest1Filter implements Filter {    @Override    public void doFilter(HttpRequest httpRequest, FilterChain filterChain) {        // do        System.out.println(this.getClass().getSimpleName() + " before " + System.currentTimeMillis());        filterChain.doFilter(httpRequest);        // after        System.out.println(this.getClass().getSimpleName() + " end " + System.currentTimeMillis());    }}package com.example.ownertest.dm.filter;/** * @Author: linear.zw * @Date: 2023/10/26 19:22 */public class ForTest2Filter implements Filter {    @Override    public void doFilter(HttpRequest httpRequest, FilterChain filterChain) {        // do        System.out.println(this.getClass().getSimpleName() + " before " + System.currentTimeMillis());        filterChain.doFilter(httpRequest);        // after        System.out.println(this.getClass().getSimpleName() + " end " + System.currentTimeMillis());    }}
  • FilterChain/StandardFilterChain
package com.example.ownertest.dm.filter;/** * @Author: linear.zw * @Date: 2023/10/26 19:23 */public interface FilterChain {    void doFilter(HttpRequest httpRequest);    void addFilter(Filter filter);}package com.example.ownertest.dm.filter;import java.util.List;import com.google.common.collect.Lists;/** * @Author: linear.zw * @Date: 2023/10/26 19:24 */public class StandardFilterChain implements FilterChain {    private List<Filter> filterList = Lists.newArrayList();    private int currentIndex = 0;    @Override    public void doFilter(HttpRequest httpRequest) {        if (currentIndex == filterList.size()) { return; }        Filter filter = filterList.get(currentIndex);        currentIndex = currentIndex + 1;        filter.doFilter(httpRequest, this);    }    @Override    public void addFilter(Filter filter) {        if (filterList.contains(filter)) {            return;        }        filterList.add(filter);    }}


内容剩余60%,完整内容可点击下方链接查看:一文聊聊代码的可读性-阿里云开发者社区

阿里云开发者社区,千万开发者的选择。百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,尽在:阿里云开发者社区-云计算社区-阿里云