有时候不想动脑子,就懒得看源码又不像浪费时间所以会看看书,但是又记不住,所以决定开始写"抄书"系列。本系列大部分内容都是来源于《 图解设计模式》(【日】结城浩 著),内容仅用于个人学习记录,可随意转载。
Iterator 模式 :一个一个遍历。
迭代器模式最常见的使用是使用Java 集合类时, 准确的说是 java.util.Collection 的实现类都具备了迭代器的类型,其实现也非常简单。
迭代器模式中登场的角色有:
类图如下:
以上述内容举个例子如下:
// 集合
public interface Aggregate<T> {
/**
* 获取迭代器
* @return
*/
Iterator<T> iterator();
}
// 迭代器
public interface Iterator<T> {
/**
* 是否存在下一个元素
* @return
*/
boolean hasNext();
/**
* 获取下一个元素
* @return
*/
T next();
}
// 具体的集合
public class ConcreteAggregate implements Aggregate<String> {
private final String[] designDemos = new String[10];
public ConcreteAggregate() {
// 初始化数据集
for (int i = 0; i < designDemos.length; i++) {
designDemos[i] = String.valueOf(i);
}
}
public int getLength() {
return designDemos.length;
}
public String get(int index){
// TODO : 边界校验
return designDemos[index];
}
@Override
public Iterator<String> iterator() {
return new ConcreteIterator(this);
}
}
// 具体的迭代器
public class ConcreteIterator implements Iterator<String> {
private ConcreteAggregate concreteAggregate;
private int index = 0;
// TODO : 入参改造为面向接口
public ConcreteIterator(ConcreteAggregate concreteAggregate) {
this.concreteAggregate = concreteAggregate;
}
@Override
public boolean hasNext() {
return index < concreteAggregate.getLength();
}
@Override
public String next() {
// TODO : 一些范围校验
final String info = concreteAggregate.get(index);
index += 1;
return info;
}
}
// 测试类如下:
public class IteratorDemoMain {
public static void main(String[] args) {
final Aggregate demoAggregate = new ConcreteAggregate();
final Iterator<String> iterator = demoAggregate.iterator();
while (iterator.hasNext()){
final String next = iterator.next();
System.out.println("next = " + next);
}
}
}
迭代器模式的典型应用就是 Java 中的 Collection 以及其子类,这个由于太熟悉就不再这里赘述。
而在日常使用中,个人也没有自定义过迭代器模式使用。
引入Iterator 设计模式可以将遍历和实现分离开来。
如下即使 DemoAggregate 中实现从数组变成了 List 或者其他自定义结构,在这里的遍历都不需要修改:
public class IteratorDemoMain {
public static void main(String[] args) {
final Aggregate demoAggregate = new DemoAggregate();
// 这里的遍历完全不再依赖于 DemoAggregate
final Iterator<String> iterator = demoAggregate.iterator();
while (iterator.hasNext()){
final String next = iterator.next();
System.out.println("next = " + next);
}
}
}
相关的设计模式 :
Adapter 模式 :加个适配器以便于复用
Adapter 模式也被称为 Wrapper模式(包装器模式),适配器模式有两种:
类适配器模式(使用继承的适配器): 类图如下,由实现了 Target 接口 (适配器接口)的 Adapter (适配器类) 通过继承 Adaptee (被适配的类)的方式来对 Adaptee 进行适配。在实际使用时暴露给外界的是 Target 接口,在 Target 的方法中则实现了对 Adaptee 的适配。
对象适配器模式(使用委托的适配器):类图如下,Adapter (适配器)通过持有 Adaptee(被适配的类) 来进行适配,外界调用 Target(适配器接口)的方法时实际上则是通过 Adapter 对 Adaptee 进行了适配后的结果。
Adapter 模式中登场的角色有:
该模式意在通过继承 Adaptee 的方式来对其进行适配, 如下:
public interface Target {
void targetMethodA();
}
public class Adaptee {
public void methodA(){
System.out.println("Adaptee.methodA");
}
}
public class Adapter extends Adaptee implements Target {
@Override
public void targetMethodA() {
System.out.println("Adapter.targetMethodA");
methodA();
}
}
public class Client {
public static void main(String[] args) {
Target target = new Adapter();
target.targetMethodA();
}
}
public class Adaptee {
public void methodA() {
System.out.println("Adaptee.methodA");
}
}
public interface Target {
void targetMethodA();
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void targetMethodA() {
System.out.println("Adapter.targetMethodA");
adaptee.methodA();
// TODO : do something
}
}
public class Client {
public static void main(String[] args) {
Target target = new Adapter();
target.targetMethodA();
}
}
下面我们来看 适配器模式在现实中的应用,如下:
Spring Aop 是通过 Advice 来增强代理类的功能, 在 Advice 的基础上创建了多个子接口和实现类,BeforeAdvice (方法执行前执行)、AfterAdvice(方法执行后执行) 等。如下图:
实际上Spring 需要 MethodInterceptor 来完成方法拦截。因此,对于 MethodBeforeAdvice、ThrowsAdvice、AfterReturningAdvice 类型本身并非是 MethodInterceptor 类型的 Advice 增加了适配器来转换为对应的 MethodInterceptor (MethodBeforeAdvice 转为 MethodBeforeAdviceInterceptor,ThrowsAdvice 转为 ThrowsAdviceInterceptor,AfterReturningAdvice 转为 AfterReturningAdviceInterceptor)。
Spring Aop 的完整分析流程如有需要详参:Spring源码分析十二:@Aspect方式的AOP上篇 - @EnableAspectJAutoProxy
如下 AfterReturningAdviceAdapter 将 AfterReturningAdvice 转换为 AfterReturningAdviceInterceptor 类型:
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}
在 Spring Mvc 中 由于有多种 HandlerMapping (处理器映射),他们会依据各自的规则扫描并将合适的方法作为自己的处理器。如 RequestMappingHandlerMapping 就是我们常见的会扫描容器中 被 @ResquestMapping 注解修饰的方法并封装成 handler,当我们发起 http 调用如果调用地址匹配到了 RequestMappingHandlerMapping 中的 handler, 则会直接调用handler 来处理该次请求。这便是简化版的 Spring mvc 流程。由于 HandlerMapping 有多种就存在多种 handler,Spring mvc 为了兼容这种情况,则 通过 HandlerAdapter 来对不同的 Handler进行适配。
Spring mvc 完成的分析流程如有需要详参: Spring源码分析二十二:Spring MVC③ DispatcherServlet的逻辑
如下是 HandlerAdapter 的定义:
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
在 DispatcherServlet#getHandlerAdapter 中会获取handler 对应的适配器,在后面通过HandlerAdapter#handle 来处理对应的handler。
// org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
相关的设计模式 :
以上:内容部分参考
《 图解设计模式》
https://blog.csdn.net/qq_37774171/article/details/122643900#t9
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正