设计模式学习笔记--适配器(Adapter)模式

原创 2014年03月31日 00:33:45


写在模式学习之前


       什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。

       设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许你根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以“模式专家”的角度来看,都是最佳的设计,不得不说是“最佳的模式实践”,这是因为你积累了很多的实践经验,知道“在什么场合代码应该怎么写”,这本身就是设计模式。

       有人说:“水平没到,学也白学,水平到了,无师自通”。诚然,模式背熟,依然可能写不出好代码,更别说设计出好框架;OOP理解及实践经验到达一定水平,同时也意味着总结了很多好的设计经验,但"无师自通",却也未必尽然,或者可以说,恰恰是在水平和经验的基础上,到了该系统的学习一下“模式”的时候了,学习一下专家总结的结果,印证一下自己的不足,对于提高水平还是很有帮助的。

       本系列的设计模式学习笔记,实际是对于《Java与模式》这本书的学习记录。


适配器(Adapter)模式定义


适配器模式把一个类的接口(源)变换成客户端所期待的另一种接口(目的),从而使 原本 因接口不匹配而无法在一起工作的两个类能够在一起工作。

名称的由来:

就像变压器,把一种电压变换成另一种电压。美国的生活用电110 V,中国的220 V,在中国使用美国的电器,就必须有一个能把220 V电压转换成110 V电压的变压器。而这正像是本模式所做的事,因此此模式也常常被称为变压器模式。

适配器模式的两种形式:

适配器模式有“类的适配器模式”和“对象的适配器模式”两种不同的形式。


类的适配器模式


在这种方式中,适配器(Adapter)和源(Adaptee)是继承的关系。


模式所涉及的角色有:

(1)目标(Target)角色:这就是所期待得到的接口。注意,由于这里讨论的是类适配器模式,因此目标不可以是类。

(2)源(Adaptee)角色:现有需要适配的接口。

(3)适配器(Adapter)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

代码实现:

interface Target
{
	void sampleOp1();	//源类有这个方法
	void sampleOp2();
}
class Adaptee
{
	public void sampleOp1(){};
}
class Adapter extends Adaptee implements Target
{
	public void sampleOp2(){};	//由于源类没有这个方法,因此适配器类补充上这个方法
}

对象的适配器模式


在这种方式中,适配器(Adapter)和源(Adaptee)是委派的关系,“适配器”委派“源”,可以通过构造函数或者set方法把“源”传入适配器。


模式所涉及的角色有:

(1)目标(Target)角色:这就是所期待得到的接口。目标也可以是具体的或抽象的类。

(2)源(Adaptee)角色:现有需要适配的接口。

(3)适配器(Adapter)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

代码实现:

interface Target
{
	void sampleOp1();	//源类有这个方法
	void sampleOp2();
}
class Adaptee
{
	public void sampleOp1(){};
}
class Adapter implements Target
{
	private Adaptee adaptee;
	public Adapter(Adaptee adaptee)
	{
		super();
		this.adaptee = adaptee;
	}
	//源类有这个方法,直接委派
	public void sampleOp1()
	{
		adaptee.sampleOp1();
	}
	public void sampleOp2(){};	//由于源类没有这个方法,因此适配器类补充上这个方法
}

在什么情况下使用适配器模式


(1)系统需要使用现有的类,而此类的接口不符合系统的需要。

(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。

(3)在设计里,如果需要改变多个已有的子类的接口,对于“类的适配器模式”,需要做多个适配器类,分别继承各个子类,这不实际,更经常使用“对象的适配器模式”。


JDK1.2之前没有Iterator(集合迭代器),只有Enumeration,如下代码演示一个例子,提供一个“从Enumeration到Iterator”适配器。

import java.util.*;
public class Enumeration2Iterator implements Iterator
{
	Enumeration enu;
	public Enumeration2Iterator(Enumeration enu)
	{
		this.enu = enu;
	}
	public boolean hasNext()
	{
		return enu.hasMoreElements();
	}
	public Object next()
	{
		return enu.nextElement();
	}
	public void remove()
	{
		throw new UnsupportedOperationException();
	}
}

缺省适配(Default Adapter)模式


(1)适配器模式还有一个特例,被称作“缺省适配(Default Adapter)模式”,“缺省适配模式”为一个接口提供缺省实现,这里子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。缺省适配模式,是一种平庸化的适配器模式,它对目标接口提供了“平庸化”的实现或者空实现。

(2)缺省适配模式的中心是一个缺省适配类。这个类应当是抽象类,因为这个类不应当实例化,它的实例化也没有用处。

(3)但是缺省适配类所提供的方法却应当是具体的方法,而不是抽象的方法,因为按照模式的用意,这些方法之所以存在,就是为了提供默认实现,以便缺省适配类的具体子类可以按照需要只实现需要实现的方法,忽略不需要实现的方法。

代码演示:

interface 和尚
{
	void 吃斋();
	void 念经();
	void 习武();
}
//这个抽象的天孤星就是一个适配器类,鲁智深借助于“适配器模式”实现了“和尚”接口,达到剃度的目的
abstract class 天孤星 implements 和尚
{
	public void 吃斋() {}
	public void 念经() {}
	public void 习武() {}
}
class 鲁智深 extends 天孤星
{
	public void 习武()
	{
		//do something
	}
}

更多了解


(1)如下代码所示的CollectionData也是一个适配器设计模式的实例,它将Generator适配到CollectionData的构造器上。Java编程思想的作者Bruce Eckel认为,这也许并非是适配器的严格定义,但它符合适配器思想的基本精神。

(2)代码如下

import java.util.*;
//Generator是个工具类,用于实例化对象的
interface Generator<T>
{
	T next();
}
class BasicGenerator<T> implements Generator<T>
{
	private Class<T> type;
	public BasicGenerator(Class<T> type)
	{
		this.type = type;
	}
	public T next()
	{
		try
		{
			return type.newInstance();
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}
	public static <T> Generator<T> create(Class<T> type)
	{
		return new BasicGenerator<T>(type);
	}
}
//CollectionData是个适配器类,用于把Generator适配到CollectionData上
class CollectionData<T> extends ArrayList<T>
{
	public CollectionData(Generator<T> gen,int quality)
	{
		for(int i=0;i<quality;i++)
		{
			add(gen.next());
		}
	}
	public static <T> CollectionData<T> list(Generator<T> gen,int quality)
	{
		return new CollectionData<T>(gen,quality);
	}
}


结构模式(Structural Pattern)小结


结构模式(Structural Pattern)一共有七种,分别是:适配器模式、装饰模式、合成模式、代理模式、享元模式、门面模式、桥梁模式。

大致总结如下:

  最大特点 典型应用
适配器模式 利用对象的功能,并转换其接口 日常工作,入目尽是适配器,DAO适配,Cache功能适配,等等
装饰模式 对象层面的功能增强,接口不变 Java I/O类库的设计
合成模式 树枝、叶子同样对待 分类树、权限树等
代理模式 代表人 WebService 的本地代理,权限访问代理,引用计数代理等
享元模式 共享对象,减小内存占用 编译器系统,Java String
门面模式 统一对外接口,方便调用 基于SOA框架编程中,不同系统之间的接口
桥梁模式 解耦 大多数的驱动器,包括JDBC Driver

版权声明:本文为博主原创文章,未经博主允许不得转载。

JAVA设计模式初探之适配器模式

1. 概述   将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。 2. 解决的问题   即Adapter模式使得原本由于接口不...

Java模式(适配器模式)

今天看了下Java中的适配器模式,以下就来小做下总结和谈谈感想,以便日后使用。 首先,先来先讲讲适配器。适配就是由“源”到“目标”的适配,而当中链接两者的关系就是适配器。它负责把“源”过度到“目标”。...

一个示例让你明白适配器模式

本文讨论适配器模式。适配器模式是23中设计模式之一,它的主要作用是在新接口和老接口之间进行适配。它非常像我们出国旅行时带的电源转换器。为了举这个例子,我还特意去京东上搜了一下电源转换器,确实看到了很多...

Java设计模式之适配器模式

概述适配器模式是结构型设计模式之一,在不修改原来两个模块代码的情况下,将两个不兼容的类融合在一起,符合开闭原则.扩展阅读适配器模式原理及实例介绍定义适配器模式把一个类的接口变换成客户端所期待的另一种接...
  • wbwjx
  • wbwjx
  • 2016年08月06日 18:54
  • 1393

手动编写JDBC连接池应用适配器和装饰者模式

背景:      为了对DBUtil更好的理解,所以决定自己手动编写一个连接池,众所周知,DBUtil是一个操作数据库的工具类,是对jdbc的简单封装,不会损耗数据库的性能,所以有的公司为了追求性能...

MySQL的存储引擎造成的事务无法回滚

MySQL中表引擎造成的不能建立外键,事务不能回滚的问题

设计模式》学习笔记--适配器Adapter

欢迎转载,请注明出处。 1、核心意图:     将一个类的接口转换成客户希望的另外一个接口,从而使得原本由于接口不兼容而不能一起工作的类可以一起工作。 该模式的目标是通过一个代理(这里是...

设计模式C++学习笔记之八(Adapter适配器模式)

适配器模式,使用之处比较特殊,不属于常规设计模式,主要用于不同系统之间的处理。是将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。...

设计模式C++学习笔记之八(Adapter适配器模式)

设计模式C++学习笔记之八(Adapter适配器模式) 适配器模式,使用之处比较特殊,不属于常规设计模式,主要用于不同系统之间的处理。是将一个类的接口转换成客户希望的另外一个接口。Adapter...

设计模式学习笔记(七)之适配器模式(Adapter)

好长时间没写学习笔记了,由于前段时间一直在准备校招,现在offer也签了,基本定了下来,可以继续了,今天抽点时间继续学习设计模式,今天学习的是适配器模式; 设计模式学习笔记(一)之单例模式(...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式学习笔记--适配器(Adapter)模式
举报原因:
原因补充:

(最多只允许输入30个字)