设计模式之适配器模式


参考资料:《大话设计模式》


举个通俗易懂的例子,有些国家用110V电压,而我们国家用220V,因此我们的电器,比如笔记本电脑是不能什么电压都能用的,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西的东西。


1.定义

适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适配器有两种类型,类适配器模式和对象适配器模式,由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而java不支持多重继承,所以我们这里主要讲的是对象适配器。


它由以下三种角色组成:

Target(目标角色):客户端想要实现的接口。也可以是具体或抽象的类。

Adaptee(源角色):需要适配的接口

Adapter(适配器角色):把源接口适配成目标接口,继承源接口,实现目标接口



/**
 * @author 
 * @date 2017.12.01
 * @function 目标类:可以是具体或抽象的类,也可以是接口
 */
public class Target {
	public	void request(){
		System.out.println("普通请求!");
	}
}
/**
 * @author 
 * @date
 * @function 需要适配的类
 */
public class Adaptee {
	public void specificRequest(){
		System.out.println("特殊请求");
	}
}
/**
 * @author 
 * @date
 * @function 适配器类
 */
public class Adapter extends Target{
	private Adaptee adaptee = new Adaptee();  //通过关联的形式建立一个私有的Adaptee对象
	
	public void request(){
		adaptee.specificRequest(); //表面上调用request()方法实际上调用specificRequest()方法
	}
}
/**
 * @author 
 * @date 2017.12.01
 * @function 客户端代码
 */
public class Client {

	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Target target = new Adapter();
		target.request(); //对客户端而言,我只需要调用目标方法,至于适配工作由适配器完成
		
	}

}

2. 适应场景

(1) 当系统的数据和行为都正确,但接口不符时,应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。

(2)想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不同时,就应该考虑用适配器模式,即两个类所做的事情相同或类似,但是具有不同的接口。

(3) 常用于设计系统使用第三方开发组件时,第三方组件的接口与自己的系统接口不相同,此时没有必要为迎合三方组件和修改系统接口,在这种情况下,尽管是开发的设计阶段,也可以考虑用适配器模式。

3. 需要注意的是:

在开发的初期,有小的接口不统一问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。


4. Java I/O 中的适配器模式

在Java的I/O类库中,大量使用了适配器模式,如将字符串数据转变成字节数据保存到文件中,将字节数据转变成流数据等。下面以InputStreamReader类为例介绍适配器模式。

以下截了InputStreamReader类的部分源码:


public class InputStreamReader extends Reader {

    private final StreamDecoder sd;

    /**
     * Creates an InputStreamReader that uses the default charset.
     *
     * @param  in   An InputStream
     */
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }
    public int read() throws IOException {
        return sd.read();
    }



结合类结构图和源码,可以看出InputStreamReader类继承了Reader抽象类,并且通过组合的形式间接地(通过StreamDecoder类)持有InputStream的引用,因为从byte到char要经过编码。但是创建InputStreamReader对象必须在构造函数中传入一个InputStream的实例。InputStreamReader的作用就是将InputStream适配到Reader上。





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值