天天看点

设计模式学习笔记——适配器模式适配器模式

适配器模式

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

结构图

设计模式学习笔记——适配器模式适配器模式

代码实现

Target:客户期待的接口

/**
 * 客户期待的接口
 * @author xukai
 * 2016年3月22日 下午12:57:38
 */
public class Target {

	public void request(){
		System.out.println("普通请求");
	}
	
}
           

Adaptee:需要适配的类

/**
 * 需要适配的类
 * @author xukai
 * 2016年3月22日 下午12:58:37
 */
public class Adaptee {

	public void specificRequest(){
		System.out.println("特殊请求");
		
	}
	
}
           

适配器类Adapter:

/**
 * 适配器类:将源接口装换成目标接口
 * @author xukai
 * 2016年3月22日 下午12:59:15
 */
public class Adapter extends Target {

	private Adaptee adaptee = new Adaptee();
	
	@Override
	public void request() {
		adaptee.specificRequest();
	}
	
}
           

客户端:

public class Client {

	public static void main(String[] args) throws ClassNotFoundException {
		Target target = new Adapter();
		target.request();
		
	}
	
}
           

Console:

特殊请求
           

对客户端来说,调用的是Adapter的方法,实际上是调用的Adaptee的方法。 适配器一词最早来自于电力行业中,如:每个国家的标准电压不同,有的是220V,有的是110V,这个时候就需要适配器从中转换一下。

demo

问题:姚明刚参加NBA的时候,不懂英文,听不懂教练的指挥,使用适配器处理。

结构图

设计模式学习笔记——适配器模式适配器模式

代码实现

球员类:

/**
 * 球员类
 * @author xukai
 * 2016年3月22日 下午1:25:23
 */
public abstract class Player {

	protected String name;
	
	public Player(String name) {
		this.name = name;
	}
	
	public abstract void attack();
	
	public abstract void defense();
}
           

每个具体位置的球员: 前锋

/**
 * 前锋
 * @author xukai
 * 2016年3月22日 下午1:34:51
 */
public class Forwards extends Player {

	public Forwards(String name) {
		super(name);
	}

	@Override
	public void attack() {
		System.out.println("前锋" + name + "进攻");
	}

	@Override
	public void defense() {
		System.out.println("前锋" + name + "防守");
	}

}
           

中锋

/**
 * 中锋
 * @author xukai
 * 2016年3月22日 下午11:18:21
 */
public class Center extends Player {

	public Center(String name) {
		super(name);
	}

	@Override
	public void attack() {
		System.out.println("中锋" + name + "进攻");
	}

	@Override
	public void defense() {
		System.out.println("中锋" + name + "防守");
	}

}
           

后卫

/**
 * 后卫
 * @author xukai
 * 2016年3月22日 下午1:45:49
 */
public class Guards extends Player {

	public Guards(String name) {
		super(name);
	}

	@Override
	public void attack() {
		System.out.println("后卫" + name + "进攻");
	}

	@Override
	public void defense() {
		System.out.println("后卫" + name + "防守");
	}

}
           

但是姚明属于外籍中锋

/**
 * 外籍中锋
 * @author xukai
 * 2016年3月22日 下午1:46:40
 */
public class ForeignCenter {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public void 进攻(){
		System.out.println("外籍中锋" + name + "进攻");
	}
	
	public void 防守(){
		System.out.println("外籍中锋" + name + "防守");
	}
	
}
           

需要适配器,翻译者类:

/**
 * 翻译者
 * @author xukai
 * 2016年3月22日 下午10:53:07
 */
public class Translator extends Player {

	private ForeignCenter wjzf = new ForeignCenter();
	
	public Translator(String name) {
		super(name);
		wjzf.setName(name);
	}

	@Override
	public void attack() {
		wjzf.进攻();
	}

	@Override
	public void defense() {
		wjzf.防守();
	}

}
           

客户端:

public class Client {

	public static void main(String[] args) {
		Player b = new Forwards("巴蒂尔");
		b.attack();

		Player m = new Guards("麦克");
		m.attack();

		Player ym = new Translator("姚明");
		ym.attack();
		ym.defense();

	}

}
           

Console:

前锋巴蒂尔进攻
后卫麦克进攻
外籍中锋姚明进攻
外籍中锋姚明防守
           

姚明听不懂教练指挥,让姚明立马学习说英语,不行,让教练说中文,也不行,只能中间添加一个翻译员。

总结

当系统的数据和行为都正确,但是接口不符时,可以考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。 适配器模式主要应用于复用一些现存的类,但是接口又与复用环境要求不一致的情况。 使用一个已经存在的类,但它的接口,即方法和要求不相同时( 两个类所做的事情相同或者相似,但具有不同的接口),使用适配器模式,从而达到客户代码可以统一调用同一接口,简单、直接、紧凑化。

继续阅读