java设计模式——适配器模式

11 篇文章 0 订阅
3 篇文章 0 订阅

名词解释

Adapter Pattern

将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份

应用背景

我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口。 怎么办?

使用Adapter,在这两种接口之间创建一个混合接口(混血儿).

**个人理解:**其实就是一种兼容性思维,Adaptor 要把Adaptee 干的是通过自己转化一次,因为 Adaptee 不满足相关的接口需要,但是Adaptor 满足,而 Adaptor 只是起到了中间人的角色,真正干活还是调用的 Adaptee 的方法

写法

实现Adapter方式,其实"think in Java"的"类再生"一节中已经提到,有两种方式:组合(composition)和继承(inheritance).

继承实现(类适配器)

假设我们要打桩,有两种接口:

方形桩

public interface ISquarePeg {
    public void insert(String str);
}

圆形桩

public interface IRoundPeg {
    public void insertIntoHole(String msg);
}

各自有一个实现类

public class SquarePeg implements ISquarePeg {
    public void insert(String str){
        System.out.println("SquarePeg insert():"+str);
    }
}
public class RoundPeg implements IRoundPeg {
    public void insertIntoHole(String msg) {
        System.out.println("RoundPeg insertIntoHole():"+msg);
    }
}

现在有一个需求,要在打圆形桩的方法里面干打方形桩的活(这就是适配),那么可以通过如下的继承关系来实现

public class PegAdapter extends SquarePeg implements IRoundPeg {
    public void insertIntoHole(String str){ super.insert(str);} //在圆形桩的方法里干打方形桩的活
}

从这个例子也可以看出,使用适配器模式最好是 Adaptor 和 Adaptee 的适配方法的参数和返回值相同或者相近,当然不符合这个条件也是没有问题的,因为方法的封装本身就可以做很多兼容性处理。

组合实现(对象适配器)

或者可以在打原型桩的类中持有打方形桩的对象

public class PegAdapter implements IRoundPeg {
    private ISquarePeg squarePeg; 

    public PegAdapter(ISquarePeg squarePeg) {
        this.squarePeg = squarePeg;
    }

    @Override
    public void insertIntoHole(String msg) {
        this.squarePeg.insert(msg); //持有 Adaptee 的引用,让引用干活
    }
}

Pluggable Adapters

可以动态的获取几个adapters中一个。使用Reflection技术,可以动态的发现类中的Public方法。

比如我们有一个登陆接口

public interface LoginAdapter {
    boolean support(Object adapter);
    String login(String id, Object adapter);
}

有多个实现类,有QQ登陆:

public class LoginForQQAdapter implements LoginAdapter {
    public boolean support(Object adapter) {
        return adapter instanceof LoginForQQAdapter;
    }
    public String login(String id, Object adapter) {
        return "QQ登陆成功";
    }
}

有微信登陆

public class LoginForWechatAdapter implements LoginAdapter {
    public boolean support(Object adapter) {
        return adapter instanceof LoginForWechatAdapter;
    }
    public String login(String id, Object adapter) {
        return "微信登陆成功";
    }
}

。。。

还有很多其他的登陆方式,这个时候,我们可以这样来做一个动态的,支持无限扩展的适登陆适配器

private String processLogin(String key,Class<? extends LoginAdapter> clazz){
        try{
            //适配器不一定要实现接口
            LoginAdapter adapter = clazz.newInstance();
            //判断传过来的适配器是否能处理指定的逻辑
            if(adapter.support(adapter)){
                return adapter.login(key,adapter);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return "登陆失败";
    }

上面的代码其实就有些Spring中

应用举例

  • Spring AOP 中 AdvisorAdapter

    public interface AdvisorAdapter {
    	boolean supportsAdvice(Advice var1);
    	MethodInterceptor getInterceptor(Advisor var1);	
    }
    

    这种写法是不是有上面loginAdaptor的影子,它有三个实现类MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter 和
    ThrowsAdviceAdapter。看下MethodBeforeAdviceAdapter 类

    class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
        MethodBeforeAdviceAdapter() {
        }
        public boolean supportsAdvice(Advice advice) {
        	return advice instanceof MethodBeforeAdvice;
        }
        public MethodInterceptor getInterceptor(Advisor advisor) {
            MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
        }
    }
    
    • Spring MVC 中 HandlerAdapter

在这里插入图片描述

​ 其适配调用的关键代码还是在DispatcherServlet 的doDispatch()方法中,doDispatch()方法调用了getHandlerAdapter()方法,代码如下:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if(this.handlerAdapters != null) {
    	Iterator var2 = this.handlerAdapters.iterator();
        while(var2.hasNext()) {
        	HandlerAdapter ha = (HandlerAdapter)var2.next();
            if(this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler adapter [" + ha + "]");
            }
            if(ha.supports(handler)) { //在这里判断各适配器是否兼容
                return ha;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值