适配器模式

适配器<Adapter>模式

 

 

    从第一本设计模式书《Java设计模式》(专业教材)看这个模式的时候大概明白了意思,觉得会了但是总是感觉不对。接着找来了第二本书相同名字是老外写的。例子很是好,但是和第一本书表达的意思似乎是相同的但是例子相差不小。最不爽的是两本书有着各自的分类标准,名词都不一样。如MouseAdapter 一个叫单接口模式一个叫角标识适配器搞的很晕.. 但自己都搞不清它为什么是适配器.于是找来了第三本书参考为了弄清分类问题。有点纠结...

 

 

简介:

    这种模式最初是为建筑设计而服务的。软件设计模式只是借用了人间的原理而已。适配器模式在生活中很是常见笔记本的电源适配器,可以使用在110~220V之间变化的电源,这就是笔记本能正常工作的原因所在。

 

模式设计图

 

 

 

 

引入了C物体以后可以C适合了A的接口,同时也适合了B的接口,三个物体就可以组合成一个完整的个体.如图:

 

 

 

 

定义<Adapter Pattern>

   Convert the interface of a class into another interface clients expects .Adapter lets classes work together that count not otherwise because of incompatible interfaces.(将一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作)

使用环境:

只要记住一点就可以:你有必要修改一个已经投产的接口时适配器模式可能是最适合的模式。例如系统的功能需要扩展的时候,需要使用一个已有的或者是新建立的类,但是这个类有不符合系统的接口,怎么办?使用该模式。

注意事项(有部分时间纠结在这)

适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是为了解决正在服役的项目,没有一个分析师会在设计的时候考虑用它。

下面是实例:

例子1

某部门项目经理带了一个项目,做人力资源管理的,该项目是由总公司发起的,公司总人数大概在700人左右。项目分为三大模块:人员信息管理、薪酬管理、职位管理。当时业务人员明确了是所有员工的所有信息,所有员工包括在职的,离职的退休的暂时不考虑。于是设计了一个UserInfo存储所有用户的信息。(get方法隐藏了)

接口是:

/**
 * 员工信息接口
 * @author wlh
 */
public interface IUserInfo {
	//获得用户名
	public String getUserName();
	//获得职位
	public String getJobPosition();
	//获得手机号码
	public String getMobleNumber();
	//获得办公室电话
	public String getOfficeTelNumber();
	//获得家庭地址
	public String getHomeAddress();
	//获得接听电话
	public String getHomeTelNumber();
	
}

  

 具体的实现类:

public class UserInfo implements IUserInfo{
	public String getUserName() {
		System.out.println("这个员工叫....");
		return null;
	}
	public String getJobPosition() {
		System.out.println("这个员工职位是老板....");
		return null;
	}
	public String getMobleNumber() {
		System.out.println("这个员工电话是....");
		return null;
	}
	public String getOfficeTelNumber() {
		System.out.println("这个员工工作电话是....");
		return null;
	}
	public String getHomeAddress() {
		System.out.println("这个员工家庭地址是....");
		return null;
	}
	public String getHomeTelNumber() {
		System.out.println("这个员工家庭电话....");
		return null;
	}

}

 

 

 

 

 

这个项目投产后运行的比较好,没出现什么问题。但是突然间公司招聘员工的方式发生了变化,公司从劳动服务公司借了一批低技术、低工资的人员充当公司员工,从事特殊项目。人力资源部门找到他们说要添加一项功能,他们老大看有钱可赚就立刻答应了。调研后才发现挺麻烦的:虽然他们和公司的员工干活没多少差别,但是他们的人的人员信息、工资情况和福利信息都由老动服务公司管理并且有一套自己的管理系统。劳动服务公司将基本信息放在了HashMap里。

接口:

 

public interface IOutUser {

	//基本信息 包括姓名 性别 手机号等
	public Map<String, String> getUserBaseInfo();
	//工作区域信息
	public  Map<String, String> getUserOfficeInfo();
	//用户的家庭信息
	public  Map<String, String> getUserHomeInfo();
	
}

 

 

 具体实现类

public class OuterUser implements IOutUser{

	public Map<String, String> getUserBaseInfo() {
		HashMap<String, String> hash=new HashMap<String, String>();
		//从数据库取得用户基本信息
		hash.put("名字", "该用户角..");
		hash.put("电话", "该用户电话..");
		return hash;
	}
	public Map<String, String> getUserOfficeInfo() {
		HashMap<String, String> hash=new HashMap<String, String>();
		//从数据库取得用户基本信息
		hash.put("办公室电话", "该用户角..");
		hash.put("职位", "该用户职位是老板..");
		return hash;
	}
	public Map<String, String> getUserHomeInfo() {
		HashMap<String, String> hash=new HashMap<String, String>();
		//从数据库取得用户基本信息
		hash.put("家庭地址", "该用户角..");
		hash.put("家庭电话", "该用户电话..");
		return hash;
	}
}

 

这样的话应该如何解决?适配器模式….

创建一个中转类OuterUserInfo 而它就像是一个双面派,既实现了IUserInfo同时扩展了OuterUser类。这样就能把它伪装成一个IUserInfo对象。

public class OuterUserInfo extends OuterUser implements IUserInfo {

	private Map<String ,String> baseInfo=super.getUserBaseInfo();
	private Map<String ,String> homeInfo=super.getUserHomeInfo();
	private Map<String ,String> officeInfo=super.getUserOfficeInfo();
	@Override
	public String getUserName() {
		String username=this.baseInfo.get("姓名");
		System.out.println("该用户叫做:"+username);
		return username;
	}
	@Override
	public String getJobPosition() {
		String jobPos=this.officeInfo.get("工作");
		System.out.println("工作是:"+jobPos);
		return jobPos;
	}
	public String getMobleNumber() {
		return null;
	}
	public String getOfficeTelNumber() {
		return null;
	}
	public String getHomeAddress() {
		return null;
	}
	public String getHomeTelNumber() {
		return null;
	}
}

 

 

 如果老板想查看本公司员工的电话?

public class Clinet0 {

	public static void main(String[] args) {
		//查找100个美女电话
		UserInfo user=new UserInfo();
		for(int i=0;i<100;i++){
			//不管是谁 调用一次就能获得一个电话号码
			String number=user.getMobleNumber();
			System.out.println("电话号码是:  "+number);
		}
	}
}

 

那么如果老板不想查看本公司的想看外来的怎么办?

 

public class Clinet1 {

	public static void main(String[] args) {
		//查找外来公司100个美女电话
		OuterUserInfo user=new OuterUserInfo();
		for(int i=0;i<100;i++){
			//不管是谁 调用一次就能获得一个电话号码
			String number=user.getMobleNumber();
			System.out.println("电话号码是:  "+number);
		}
	}
}

 

 

 

 

只是需要一句话 OuterUserInfo user=new OuterUserInfo();

就可以实现了该目的。

 

其实这还远远没完,现在遇到了两个问题:

1 如果劳动服务公司提供的接口适量不是一个,怎么办?总不能全部都要继承了,java可是只支持单继承。

2 如果原来的项目中此处并没有提供接口,而是需要一个类。那该如何办?

案例2

下面解决这两个问题。

问题1

如果劳动服务公司提供了不是一个接口的话,而是3

个,例如:

 

 

public interface IOuterUserBaseInfo {
	//基本信息 比如姓名 性别 手机号码
	public  Map<String,String> getUserBaseInfo();
	
}

 

public interface IOuterUserHomeInfo {

	//用户家庭信息
		public  Map<String,String> getUserHomeInfo();
}

 

public interface IOuterUserOfficeInfo {

	//工作信息  
	public  Map<String,String> getUserOfficeInfo();
}

 

 

它是将员工信息存放在3个接口的3map中。

具体的实现类是:

public class OuterUserBaseInfo  implements IOuterUserBaseInfo{

	@Override
	public Map<String, String> getUserBaseInfo() {
		HashMap<String, String> baseInfo=new HashMap<String, String>();
		//从数据库取得信息
		baseInfo.put("username", "装大户");
		baseInfo.put("电话", "*****");
		return baseInfo;
	}

}

 

public class OuterUserHomeInfo implements IOuterUserHomeInfo{

	@Override
	public Map<String, String> getUserHomeInfo() {
		HashMap<String, String> homeInfo=new HashMap<String, String>();
		//从数据库取得信息
		homeInfo.put("家庭住址", "美国");
		homeInfo.put("家庭电话", "*****");
		return homeInfo;
	}

}

 

public class OuterUserOfficeInfo implements IOuterUserOfficeInfo{

	@Override
	public Map<String, String> getUserOfficeInfo() {
		HashMap<String, String> officeInfo=new HashMap<String, String>();
		//从数据库取得信息
		officeInfo.put("职位", "boss");
		officeInfo.put("工作电话", "*****");
		return officeInfo;
	}

}

 

 

  

实际上走到现在的话,创建一个适配器但是它必须继承公司需求的类假如是A类那么就不可能在继承劳动服务公司的类,但是还要得到他们的3map此时别无选择只是能采用关联的方式,其实也是面向对象的一个思想:将某个类当成是另外的一个类的成员变量。

public class OuterUserInfo implements IUserInfo {
	// 关联
	private OuterUserHomeInfo homeInfo = null;
	private OuterUserBaseInfo baseInfo = null;
	private OuterUserOfficeInfo officeInfo = null;
	// 数据处理
	private Map<String, String> baseMap = null;
	private Map<String, String> homeMap = null;
	private Map<String, String> officeMap = null;
	// 构造函数
	public OuterUserInfo(OuterUserHomeInfo homeInfo,
			OuterUserBaseInfo baseInfo, OuterUserOfficeInfo officeInfo) {
		this.baseInfo=baseInfo;
		this.homeInfo=homeInfo;
		this.officeInfo=officeInfo;
		baseMap=this.baseInfo.getUserBaseInfo();
		homeMap=this.homeInfo.getUserHomeInfo();
		officeMap=this.officeInfo.getUserOfficeInfo();
	}
	public String getUserName() {
		String name=this.baseMap.get("名字");
		return name;
	}
	public String getJobPosition() {
		String jobPos=this.officeMap.get("jobPos");
		return jobPos;
	}
	public String getMobleNumber() {
		String telphoneNumber=this.baseMap.get("电话");
		return telphoneNumber;
	}
	public String getOfficeTelNumber() {
		String officeNum=this.officeMap.get("工作电话");
		return officeNum;
	}
	public String getHomeAddress() {
		String homeAdd=this.homeMap.get("家庭住址");
		return homeAdd;
	}
	public String getHomeTelNumber() {
		String homeNum=this.homeMap.get("家庭电话");
		return homeNum;
	}
}

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值