设计模式-类交互-非订阅

 模板

模板方法表达,

1. 一个问题有不同方式,每种方式都需要拆解成多步骤(方法)解决,可以把解决步骤定下来,形成模板。如 DispatcherServlet#doDispatch

2. 枚举一个功能的所有操作方式,封装在模板里。典型实现:RedisTemplate,子类可以重写模板类 StringRedisTemplate。

注意模板方法的划分粒度,合适的划分可以解耦,太详细就没必要,不如写一个 pipeline。

CRUD:[组装数据,rest请求,数据转换],[入库前校验,入库] 是一个模板方法的两个步骤;

计算器:canCalc(数据能不能取到),计算(数据能取到),默认值(无法计算) 就可以是 一个模板方法 的三个步骤。

看实现

org.springframework.web.servlet.DispatcherServlet#doDispatch

/**
    
 * Process the actual dispatching to the handler.
 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
 * to find the first that supports the handler class.
 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
 * themselves to decide which methods are acceptable. !
 * @param request current HTTP request
 * @param response current HTTP response
 * @throws Exception in case of any kind of processing failure
 */
@SuppressWarnings("deprecation")
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // Determine handler for the current request.
    // 责任链
	mappedHandler = getHandler(processedRequest);
    // Determine handler adapter for the current request.
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    // Actually invoke the handler.
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    // catch-deal
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

策略

这个就更常见了,但凡根据配置来,根据状态走,都是策略模式。

如果策略比较简单,用lambda实现,如《Java8实战》:

// 校验字符串只包含 数字
Validator numericValidator = new Validator((String s) -> s.matches("\\d+")); 
boolean b1 = numericValidator.validate("aaaa"); 
// 校验字符串只包含 小写字母
Validator lowerCaseValidator = new Validator((String s) -> s.matches("[a-z]+")); 
boolean b2 = lowerCaseValidator.validate("bbbb"); 

责任链

EasyExcel 用责任链模式设计了一个拦截器,自定义对单元格的操作。

看实现

<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
你只要自定义一个 执行器,就可以调到你
public class CustomSheetWriteHandler implements SheetWriteHandler {}


// 处理器加入到责任链
com.alibaba.excel.write.builder.AbstractExcelWriterParameterBuilder#registerWriteHandler

调用
com.alibaba.excel.write.builder.ExcelWriterBuilder#sheet(java.lang.String)

com.alibaba.excel.context.WriteContextImpl#WriteContextImpl

com.alibaba.excel.context.WriteContextImpl#initCurrentWorkbookHolder

com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder#WriteWorkbookHolder

com.alibaba.excel.write.metadata.holder.AbstractWriteHolder#initHandler

List<WriteHandler> handlerList = new ArrayList<>();
if (writeBasicParameter.getCustomWriteHandlerList() != null
    && !writeBasicParameter.getCustomWriteHandlerList().isEmpty()) {
    handlerList.addAll(writeBasicParameter.getCustomWriteHandlerList());
}
sortAndClearUpHandler(handlerList, true);

// com.alibaba.excel.write.metadata.holder.AbstractWriteHolder#sortAndClearUpHandler
for (WriteHandler writeHandler : cleanUpHandlerList) {
    buildChain(writeHandler, runOwn);
}

 * Execute the sheet handler chain
 * Created in the sheet in the workbook interceptors will not be executed because the workbook to
 * create an event long past. So when initializing sheet, supplementary workbook event.
 */
public SheetHandlerExecutionChain ownSheetHandlerExecutionChain;
protected void buildChain(WriteHandler writeHandler, boolean runOwn) {
    
    if (ownSheetHandlerExecutionChain == null) {
        ownSheetHandlerExecutionChain = new SheetHandlerExecutionChain((SheetWriteHandler)writeHandler);
    } else {
        ownSheetHandlerExecutionChain.addLast((SheetWriteHandler)writeHandler);
    }
}

// 责任链添加元素
// com.alibaba.excel.write.handler.chain.SheetHandlerExecutionChain#addLast
public void addLast(SheetWriteHandler handler) {
    SheetHandlerExecutionChain context = this;
    while (context.next != null) {
        context = context.next;
    }
    context.next = new SheetHandlerExecutionChain(handler);
}


// 调用处理器
com.alibaba.excel.context.WriteContextImpl#initSheet
private void initSheet(WriteTypeEnum writeType) {
    // 组装上下文 
    SheetWriteHandlerContext sheetWriteHandlerContext = WriteHandlerUtils.createSheetWriteHandlerContext(this);
    // 创建前处理
    WriteHandlerUtils.beforeSheetCreate(sheetWriteHandlerContext);
    // 创建Sheet
    if (currentSheet == null) {
        currentSheet = createSheet();
    }
    writeSheetHolder.setSheet(currentSheet);
    // 创建后处理
    WriteHandlerUtils.afterSheetCreate(sheetWriteHandlerContext);
}


com.alibaba.excel.util.WriteHandlerUtils#afterSheetCreate(com.alibaba.excel.write.handler.context.SheetWriteHandlerContext, boolean)
// 创建后处理
public static void afterSheetCreate(SheetWriteHandlerContext context, boolean runOwn) {
    // 获取执行链
    SheetHandlerExecutionChain sheetHandlerExecutionChain = getSheetHandlerExecutionChain(context, runOwn);
    if (sheetHandlerExecutionChain != null) {
        // 链式处理
        sheetHandlerExecutionChain.afterSheetCreate(context);
    }
}

// 执行链
private static SheetHandlerExecutionChain getSheetHandlerExecutionChain(SheetWriteHandlerContext context,
    boolean runOwn) {
    AbstractWriteHolder abstractWriteHolder = (AbstractWriteHolder)context.getWriteContext().currentWriteHolder();
    if (runOwn) {
        return abstractWriteHolder.getOwnSheetHandlerExecutionChain();
    } else {
        // 
        return abstractWriteHolder.getSheetHandlerExecutionChain();
    }
}




迭代器

集合强助攻:

1. 迭代器-Iterator ->

2. 比较器-Comparator

3. 拆分器-Spliterator

// 逆序排序
Comparator<Integer> comparator = Integer::compareTo;
        Stream.iterate(2, n -> n * 2).limit(3)
                .sorted(comparator.reversed()).forEach(System.out::println);


/
    拆分器
 * @param <T> the type of stream elements
 * @param seed the initial element
 * @param f a function to be applied to the previous element to produce
 *          a new element
 * @return a new sequential {@code Stream}
 */
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
    Objects.requireNonNull(f);
    Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
           Spliterator.ORDERED | Spliterator.IMMUTABLE) {
        T prev;
        boolean started;
        // 剩余元素,则执行此操作返回true,否在返回false
        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            T t;
            if (started)
                // 执行 n -> n * 2
                t = f.apply(prev);
            else {
                t = seed;
                started = true;
            }
            // 执行 list.add(prev);
            action.accept(prev = t);
            return true;
        }
    };
    // 创建流 
    return StreamSupport.stream(spliterator, false);
}


// java.util.stream.StreamSupport#stream(java.util.Spliterator<T>, boolean)
 * @param <T> the type of stream elements
 * @param spliterator a {@code Spliterator} describing the stream elements
 * @param parallel if {@code true} then the returned stream is a parallel
 *        stream; if {@code false} the returned stream is a sequential
 *        stream.
 * @return a new sequential or parallel {@code Stream}
 */
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
    Objects.requireNonNull(spliterator);
    // 创建 pipeline
    return new ReferencePipeline.Head<>(spliterator,
                                        StreamOpFlag.fromCharacteristics(spliterator),
                                        parallel);
}

// 比较器 java.util.Comparator#reversed
// 没有使用 java.lang.Integer#compareTo
/**
 * Returns a comparator that imposes the reverse ordering of this
 * comparator.
 *
 * @return a comparator that imposes the reverse ordering of this
 *         comparator.
 * @since 1.8
 */
default Comparator<T> reversed() {
    return Collections.reverseOrder(this);
}

private static class ReverseComparator2<T> implements Comparator<T>,
        Serializable
    {
        private static final long serialVersionUID = 4374092139857L;

        /**
         * The comparator specified in the static factory.  This will never
         * be null, as the static factory returns a ReverseComparator
         * instance if its argument is null.
         *
         * @serial
         */
        final Comparator<T> cmp;

        ReverseComparator2(Comparator<T> cmp) {
            assert cmp != null;
            this.cmp = cmp;
        }

        public int compare(T t1, T t2) {
            return cmp.compare(t2, t1);
        }

        public boolean equals(Object o) {
            return (o == this) ||
                (o instanceof ReverseComparator2 &&
                 cmp.equals(((ReverseComparator2)o).cmp));
        }

        public int hashCode() {
            return cmp.hashCode() ^ Integer.MIN_VALUE;
        }

        @Override
        public Comparator<T> reversed() {
            return cmp;
        }
    }


// java.util.stream.ReferencePipeline#forEach
public void forEach(Consumer<? super P_OUT> action) {
    evaluate(ForEachOps.makeRef(action, false));
}


/**
 * Constructs a {@code TerminalOp} that perform an action for every element
 * of a stream.
 *
 * @param action the {@code Consumer} that receives all elements of a
 *        stream
 * @param ordered whether an ordered traversal is requested
 * @param <T> the type of the stream elements
 * @return the {@code TerminalOp} instance
 */
static final class OfRef<T> extends ForEachOp<T> {
    final Consumer<? super T> consumer;
    OfRef(Consumer<? super T> consumer, boolean ordered) {
        super(ordered);
        this.consumer = consumer;
    }
    @Override
    public void accept(T t) {
        consumer.accept(t);
    }
}


/**
 * Evaluate the pipeline with a terminal operation to produce a result.
 *
 * @param <R> the type of result
 * @param terminalOp the terminal operation to be applied to the pipeline.
 * @return the result
 */
final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) {
    assert getOutputShape() == terminalOp.inputShape();
    if (linkedOrConsumed)
        throw new IllegalStateException(MSG_STREAM_LINKED);
    linkedOrConsumed = true;

    return isParallel()
           ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))
           : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));
}


public <S> Void evaluateSequential(PipelineHelper<T> helper,
                                   Spliterator<S> spliterator) {
    return helper.wrapAndCopyInto(this, spliterator).get();
}

// java.util.stream.AbstractPipeline#wrapAndCopyInto
final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) {
    copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator);
    return sink;
}


/**
 * Pushes elements obtained from the {@code Spliterator} into the provided
 * {@code Sink}, checking {@link Sink#cancellationRequested()} after each
 * element, and stopping if cancellation is requested.
 *
 * @implSpec
 * This method conforms to the {@code Sink} protocol of calling
 * {@code Sink.begin} before pushing elements, via {@code Sink.accept}, and
 * calling {@code Sink.end} after all elements have been pushed or if
 * cancellation is requested.
 *
 * @param wrappedSink the destination {@code Sink}
 * @param spliterator the source {@code Spliterator}
 * @return true if the cancellation was requested
 */
final <P_IN> boolean copyIntoWithCancel(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
    @SuppressWarnings({"rawtypes","unchecked"})
    AbstractPipeline p = AbstractPipeline.this;
    while (p.depth > 0) {
        p = p.previousStage;
    }

    wrappedSink.begin(spliterator.getExactSizeIfKnown());
	// pipeline
    boolean cancelled = p.forEachWithCancel(spliterator, wrappedSink);
	// 最后操作:打印输出
    wrappedSink.end();
    return cancelled;
}

final boolean forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
    boolean cancelled;
	// 遍历  iterate()中 定义的spliterator
    do { } while (!(cancelled = sink.cancellationRequested()) && spliterator.tryAdvance(sink));
    return cancelled;
}


// java.util.stream.SortedOps.RefSortingSink#end
/**
* Indicates that all elements have been pushed.  If the {@code Sink} is
* stateful, it should send any stored state downstream at this time, and
* should clear any accumulated state (and associated resources).
*
* <p>Prior to this call, the sink must be in the active state, and after
* this call it is returned to the initial state.
*/
public void end() {
    // 排序,执行 ReverseComparator2#compareTo Find end of run, and reverse range if descending
    list.sort(comparator);
    downstream.begin(list.size());
    if (!cancellationRequestedCalled) {
        list.forEach(downstream::accept);
    }
    else {
        for (T t : list) {
            if (downstream.cancellationRequested()) break;
            // 回调 OfRef#accept
            downstream.accept(t);
        }
    }
    downstream.end();
    list = null;
}

小结

从类交互 回看 组合 和  继承。

用继承-模板模式:

1. 框架中的类,你没办法改写框架类,要重写,只能用继承

2. 表达 复用用继承。三层 以内用继承。否则  嵌套层次过深不易理解,中间类方法修改会影响子类不易维护。

用组合-策略模式:

非继承的情况用 组合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值