首页 > 代码库 > 适配器模式浅谈
适配器模式浅谈
首先,我们来说一下什么是适配器:用电器做例子,笔记本电脑的插头一般都是三相的,即除了阳极、阴极外,还有一个地极。而有些地方的电源插座却只有两极,没有地极。电源插座与笔记本电脑的电源插头不匹配使得笔记本电脑无法使用。这时候一个三相到两相的转换器(适配器)就能解决此问题,而这正像是本模式所做的事情
那么,转换到代码中去我们可以理解为,使原本因接口不匹配而无法在一起工作的两个类能够在一起工作!也可以说是在不改变类原来的结构上添加新的方法!
比如,我有一个person类,这个person类有说,读两个方法,如今我需要在这个的基础上在增加写这个方法,这个”写“就是要加入的这个方法,但是就会有人会问,我们为什么不直接写一个子类,或者直接家加上一个方法呢?我的理解是,所谓的“适配”,就是再需要用的时候才用适配器,不用的时候就甩掉他,这就表现出了java编码低耦合的思想
当这个接口为了满足客户端需要,又要重新进行适配的时候,我们就可以写新的适配器,而不去影响原来类的接口
类适配:
person类:
public class Person { public void speak(){ System.out.println("speak"); } public void read(){ System.out.println("read"); } }接口
public interface Target { void speak(); void read(); void write(); }
public class NewPerson extends Person implements Target { @Override public void write() { //do something } }这个NewPerson就满足了新客户端的要求,这种叫做类适配器!这样就把write方法加入进去了,而不影响结构
对象适配
细心的朋友会发现,上一种方式有点缺陷,因为java只有单继承的关系,上面这种使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式
public class NewPerson_2 implements Target { Person person; public NewPerson_2(Person person) { this.person=person; } @Override public void speak() { this.person.speak(); } @Override public void read() { this.person.read(); } @Override public void write() { //do something } }对象适配没有用到继承,这样的好处就是能够把多个需要适配的对象都聚合在一起来适配,对象适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。
如果在团队开发当中,每个人都实现自己要实现的方法,但是大家气其实上都是写的一个接口,通过对象适配的方法,就可以把多个人实现好了类都聚合在一起使用了,当然这是一个笑话,团队发开中还有更好的模式能够替代他!
这里还有一种默认的适配器模式
public interface Target { void function1(); void function2(); }
public abstract class T implements Target { @Override public void function1() {} @Override public void function2() { // TODO Auto-generated method stub } }
public class T1 extends T { @Override public void function1() { } }
当一个接口中的东西不希望你全部都实现它的时候,可以用到这种抽象类!然后写一个子类继承他,写你需要写的方法!
WindowListener和windowAdapter就是一个例子,后者是一个抽象类,所以我们可以继承后者来完成我们的功能!
小结:
适配器模式使我们可以重用一个现有的类,以满足客户端的需要,当客户端通过接口表达其需求的时候,通常可以创建一个实现了该接口的新类,同时使该类继承自实现的现有类,这种方式既是类的适配器,他能够将客户端的调用转换为对现有类方法的调用。
当客户端没有指定它所需要的接口时,你就可以使用适配器模式。可能需要创建一个新的客户端子类,他将使用现有类的实例。这种方式通过创建一个对象适配器。将客户端的调用指向现有类的实例。如果我们不需要重写客户端可能调用的方法时,这种方式存在一定的危险性。