首页 > 代码库 > Java设计模式之适配器模式(Adapter Pattern)

Java设计模式之适配器模式(Adapter Pattern)

Adapter Pattern的作用是在不改变功能的前提下转换接口。Adapter分为两类,一类是Object Adapter, 另一类是Class Adapter。由于Class Adapter的实现需要用到多继承,而Java不支持多继承,所以这里只关注Object Adapter。


在JDK1.5之前是没有 java.util.Iterator 接口的,java.util.Enumeration 接口起着 Iterator 的作用。那么如果我们需要维护一些年代比较久远的代码,可能就会面临着没有 Iterator 的窘境。这时候 Adapter Pattern 就派上用场了。下面通过两个例子,说明如何通过 Adapter Pattern 将 Enumeration 接口与 Iterator 接口相互“转换”。


老代码适配新代码:将Enumeration转换为Iterator

查了一下API文档,发现 StringTokenizer 这个类实现了 Enumeration 接口,那就拿这个来举例吧。现在有需求,需要用 Iterator 的方式来"遍历" StringTokenizer,但是 StringTokenizer类并没有实现 Iterator 接口。因此我们需要编写一个 Adapter,将 Enumeration 接口转换成 Iterator 接口。
class IteratorAdapter implements Iterator {
	private Enumeration enume; // 保存 Enumeration 接口实现类
	
	public IteratorAdapter(Enumeration enume) {
		this.enume = enume;
	}

	/**
	 * Enumeartion的hasMoreElements()方法与Iterator的hasNext()方法功能相同,直接调用
	 */
	@Override
	public boolean hasNext() {
		return enume.hasMoreElements();
	}

	/**
	 * Enumeration的next()方法与Iterator的next()方法功能相同,直接调用
	 */
	@Override
	public Object next() {
		return enume.nextElement();
	}

	/**
	 * 由于Enumeration接口中没有此方法,所以扔异常
	 */
	@Override
	public void remove() {
		throw new UnsupportedOperationException();
		
	}
	
}

可以看到,我们实际上只是把没有实现的 Iterator 接口里的方法实现委托给了 Enumeration 接口的实现。
Adapter 的使用方法如下:
StringTokenizer st = new StringTokenizer("a b c d e f g");
		
		// 创建adapter对象,将StringTokenizer对象传进去
		IteratorAdapter strTokenAdapter = new IteratorAdapter(st);
		
		// 这时候就可以用Iterator的方式遍历没有实现Iterator接口的对象了
		while(strTokenAdapter.hasNext()) {
			out.println(strTokenAdapter.next());
		}


新代码适应老代码:将Iterator转换为Enumeration

反过来的过程就很简单的了,因为 Enumeration 接口里的方法在 Iterator 中都有定义。
class EnumerationAdapter implements Enumeration {
	private Iterator it;
	
	public EnumerationAdapter(Iterator it) {
		this.it = it;
	}

	@Override
	public boolean hasMoreElements() {
		return it.hasNext();
	}

	@Override
	public Object nextElement() {
		return it.next();
	}
	
}


像上面 IteratorAdapter 和 EnumerationAdapter 那样把要被适配的对象保存到类的成员变量里的方式,就叫 Object Adapter。而另一种 Class Adapter则是要求 Adapter 类同时继承适配的双方。比如,有一个名为Apple的类和名为Banana的类,它们的public方法不相同。现在想以调用Apple类方法的方式使用Banana类,那么对于 Class Adapter 来说,就应该让 Adapter 同时继承 Apple 和 Banana,然后通过 Adapter 完成方法调用。有兴趣的话可以用C++实现一下试试。