模板
模板方法表达,
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. 表达 复用用继承。三层 以内用继承。否则 嵌套层次过深不易理解,中间类方法修改会影响子类不易维护。
用组合-策略模式:
非继承的情况用 组合。