适配器设计模式

Gof 原文

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatibleinterfaces.

[Q&A] 适配器模式适用于哪些业务场景?

1、已经存在的类,它的方法和需求不匹配(但是方法结果相同或相似)的情况。在软件开发中,基本上任何问题都可以通过增加一个中间层来解决。
2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案,有种亡羊补牢的感觉。

适配器模式有3种形式

1・Class Adapter – This form uses java inheritance and extends the source interface, in our case Socket class.
2・Object Adapter – This form uses Java Composition and adapter contains the source object.
3・接口适配器:如果我们要实现的接口方法太多,而我们只需要用几个,都实现会很麻烦,所以引出了接口适配器,具体看下面例子

Class Adapter :Using inheritance for adapter pattern

public interface ISocketAdapter {
	public Volt get120Volt();
	public Volt get12Volt();
	public Volt get3Volt();
}
public class Socket {
	public Volt getVolt(){
		return new Volt(120);
	}
}
//Using inheritance for adapter pattern
public class SocketInheritanceAdapter extends Socket implements ISocketAdapter {

    @Override
    public Volt get120Volt() {
        return getVolt();
    }

    @Override
    public Volt get12Volt() {
        Volt v = getVolt();
        return convertVolt(v, 10);
    }

    @Override
    public Volt get3Volt() {
        Volt v = getVolt();
        return convertVolt(v, 40);
    }

    private Volt convertVolt(Volt v, int i) {
        return new Volt(v.getVoltValue() / i);
    }
}

Object Adapter :Using Composition for adapter pattern

public class SocketCompositionAdapter implements ISocketAdapter {

	//Using Composition for adapter pattern
	private final Socket sock = new Socket();
	
	@Override
	public Volt get120Volt() {
		return sock.getVolt();
	}

	@Override
	public Volt get12Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,10);
	}

	@Override
	public Volt get3Volt() {
		Volt v= sock.getVolt();
		return convertVolt(v,40);
	}
	
	private Volt convertVolt(Volt v, int i) {
		return new Volt(v.getVoltValue()/i);
	}
}

接口适配器

假如接口有这么多方法,但是我只用第一个方法,其余也实现会很麻烦

public interface DCOutput {
    int output5V();
    int output9V();
    int output12V();
    int output24V();
}

这里抽象类其实就写了空方法,等着子类去实现需要的方法。

public abstract class PowerAdapter implements DCOutput{
    protected AC220 mAC220;

    public PowerAdapter(AC220 ac220){
        this.mAC220 = ac220;
    }

    @Override
    public int output5V() {
        return 0;
    }

    @Override
    public int output9V() {
        return 0;
    }

    @Override
    public int output12V() {
        return 0;
    }

    @Override
    public int output24V() {
        return 0;
    }
}

子类继承就可以选择性的重写父类的方法了,就不需要实现接口所有的方法了

package com.demo.adapter.interfaceadapter;

import com.demo.adapter.classadapter.AC220;

/
 * Created by italkbb on 2018/1/24.
 */

public class Power5VAdapter extends PowerAdapter {

    public Power5VAdapter(AC220 ac220) {
        super(ac220);
    }

    @Override
    public int output5V() {
        int output = 0;
        if (mAC220 != null) {
            output = mAC220.output220V() / 44;
        }
        return output;
    }
}

在这里插入图片描述

适配器模式应用

适配器模式在Spring源码中的应用

在Spring中,适配器模式应用得非常广泛,例如Spring AOP中的AdvisorAdapter类,
它有3个实现类:MethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter

先来看顶层接口AdvisorAdapter

public interface AdvisorAdapter {
	boolean supportsAdvice(Advice advice);
	MethodInterceptor getInterceptor(Advisor advisor);
}
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}
}

Spring会根据不同的AOP配置来确定使用对应的Advice,与策略模式不同的是,一个方法可以同时拥有多个Advice。

适配器模式在SpringMVC源码中的应用

public class DispatcherServlet extends FrameworkServlet {
...

	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
		// Determine handler adapter for the current request.
		HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
		...
		}

...

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				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");
	}
}

适配器模式与装饰器模式的区别

适配器模式和装饰器模式都是包装器模式(Wrapper Pattern)
在这里插入图片描述

适配器模式与策略模式好像区别不大?适配器模式主要解决的是功能兼容问题,单场景适配大家可能不会和策略模式对比,但复杂场景适配大家就很容易混淆.

Java适配器设计模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一种接口,从而使原本接口不匹配的两个类能够协同工作。适配器模式有两种实现方式:类适配器和对象适配器。 类适配器使用继承的方式实现适配器。它包括三个主要角色:目标接口适配者类和适配器类。目标接口定义了客户端所期望的接口适配者类是被访问和适配的现存组件库中的组件接口适配器类继承了适配者类并实现了目标接口,通过继承和重写方法的方式将适配接口转换成目标接口。 对象适配器使用对象组合的方式实现适配器。它也包括三个主要角色:目标接口适配者类和适配器类。目标接口适配者类的定义与类适配器相同,唯一的区别是适配器类不再继承适配者类,而是将适配者对象作为构造参数传入适配器类中,在适配器类的方法中调用适配者对象的方法来实现适配适配器设计模式在以下场景中适用: 1. 已经存在的类的方法与需求不匹配,需要进行接口转换。 2. 不同产品或不同厂家的类具有相似的功能但接口不相同,需要对它们进行适配。 总结来说,适配器设计模式能够提高类的透明性和复用性,解耦目标类和适配类,提高程序的扩展性。但在编写适配器需要全面考虑,可能会增加系统的复杂性,并且过度使用适配器可能会导致代码的混乱。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Java设计模式适配器模式](https://blog.csdn.net/qq_37922483/article/details/124568177)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [java设计模式-适配器模式](https://blog.csdn.net/weixin_62862983/article/details/122536241)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值