设计模式(三)——适配器设计模式

今天复习这样一种设计模式,当客户端想要使用一个类,但是这个类的接口并不符合客户端的要求时,我们就会想到这个设计模式—— 适配器设计模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在 一起工作
适配器模式分为两种:类的适配器模式和对象的适配器模式。
首先,这两种模式的类图关系分别为:
1.类的适配器模式
2.对象的适配器模式

然后,来个实例理解理解,反正这个设计模式,我理解的时候也是想了挺长时间的,希望大家好好把握“协同”工作的意义。
1.类的适配器模式

目标接口:

package com.xdccl.zwj.AdapterDesignPatterns.ClassAdapterDesignPattern;
//目标角色:类适配器设计模式中,这里只能是一个接口
public interface Target {
	public void get110v() ;
	public void get220v() ;
}

源角色:

package com.xdccl.zwj.AdapterDesignPatterns.ClassAdapterDesignPattern;
//源角色,只具有特定的方法,如果Target接口改变,这个类是不能被修改的
//同时,这个类的接口和标准接口不同,需要这个类和实现标准接口的类协同操作(理解这里的协同的意思)
public class Adaptee {
	public void get220v(){
		System.out.println("源角色----220v");
	}
}

适配器:

package com.xdccl.zwj.AdapterDesignPatterns.ClassAdapterDesignPattern;
//适配器:对源角色进行扩展,实现了目标角色,从而使得目标角色改动时候,不用改动源角色,只要改动适配器即可 
public class Adapter extends Adaptee implements Target {

	@Override
	public void get110v() {
		System.out.println("适配器---110v");
	}

}

客户端:

package com.xdccl.zwj.AdapterDesignPatterns.ClassAdapterDesignPattern;

public class Client {
	public static void main(String args[]){
		//面向客户端的只有Target接口
		Target target = new Adapter() ;			//在需求中,这里的代码是不可以改变的
		target.get110v() ;				//这里使用的是适配器中的方法
		target.get220v() ;			//这里使用的源角色的方法
		//从代码中可以看出,都是使用target对象,却可以使用源角色和适配器中的方法,这里就体现了协同的作用
	}
	
}

如上代码所示,正确的输出应该是这样的:

适配器---110v
源角色----220v

2.对象的适配器模式

这里的目标接口和源角色的代码可以不变,需要对适配器和客户端代码进行修改:

适配器:

package com.xdccl.zwj.AdapterDesignPatterns.ObjectAdapterDesignPattern.copy;
//这里和类适配器不同的就是,需要拿到Adaptee的引用,这样,相当于是一个代理的作用了
public class Adapter implements Target {
	private Adaptee adaptee ;
	public Adapter(Adaptee adaptee){		//构造函数
		this.adaptee = adaptee ;
	}
	@Override
	public void get110v() {
		System.out.println("适配器---110v");
	}

	@Override
	public void get220v() {
		adaptee.get220v() ;
	}

}

客户端:

package com.xdccl.zwj.AdapterDesignPatterns.ObjectAdapterDesignPattern.copy;

public class Client {
	public static void main(String args[]){
		//面向客户端的只有Target接口
		Adaptee adaptee = new Adaptee() ;				//这里需要将源对象作为参数传到适配器中
		Target target = new Adapter(adaptee) ;			//对象适配器的好处就是这里的Target可以是一个类
		target.get110v() ;				//这里使用的是适配器中的方法
		target.get220v() ;			//这里使用的源角色的方法
		//从代码中可以看出,都是使用target对象,却可以使用源角色和适配器中的方法,这里就体现了协同的作用
	}
	
}

结果和类适配器模式的示例结果完全一样。

最后,在网上找了点这两种适配器模式的对比,贴上来大家自己看看吧
(1)类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
(2)对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和Adaptee的子类一起工作,因为继承是静态的关系,当适配器继承了Adaptee后,就不可能再去处理  Adaptee的子类了。
(3)对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。
(4)对于类适配器,适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法。
(5)对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然重定义Adaptee的行为比较困难,但是想要增加一些新的行为则方便的很,而且新增加的行为可同时适用于所有的源。
(6)对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee。
(7)对于对象适配器,需要额外的引用来间接得到Adaptee。

(8)建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。

看完了这些给大家抛出一个小问题,如果目标接口不是一个接口,而变成了目标类,那么代码应该做什么改变呢?完成这个小问题来检验下有没有很好的理解这个设计模式吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值