设计模式——适配器模式
来聊聊适配器吧,就如同字面意思,它通过组合与包装让对象符合使用条件。就像生活中各式各样的转换器一样。
1.情景举例
公司通过决策,想要把项目1的内容融入到项目2中。整个项目2的对象都需要在一个容器中进行注册,以方便管理。整个项目的对象也都继承自BaseObject类,容器通过操作BaseObject类型的引用管理所有的对象。现在要把项目1融入这个管理体系,自然也要把项目1的对象注册到容器中。
public abstract class BaseObject {
public abstract String getName();
}
BaseObject中只有一个抽象方法就是显示他们的具体类名。下面是项目2中原有的继承BaseObject的类
public class Obejct2_Class1 extends BaseObject {
@Override
public String getName() {
return "Class_1";
}
}
然后是项目1中的类
public class Object1_class2 {
public String getName(boolean isClassName) {
//isClassName是一个标示,如果是true就显示类全名,如果是false就显示简单类名
return isClassName ? getClass().getName() : "OB1_class2";
}
}
项目1中的getName()需要参数,与项目2中类的方法有很大不同。可是容器只认BaseObject类和他的子类,只能通过多态调用无参的getName()方法,怎么办呢?
2.使用适配器模式
适配器类似于我们生活中的转换头,例如110v电压转220v电压的转换头。他们的工作目标就是把一个不相干的物体通过包装让它看起来与正常物体一样,保证我们可以像对待一般物体一样使用它。
在上面的例子中,项目1与项目2的类继承结构不同,导致无法进入同一个容器中,这就需要我们设计一个用于项目1对象的适配器,让项目1的类在被适配之后可以被项目2的容器一视同仁。
首先通过继承项目2的基类BaseObject创造一个适配器
public class Object2Adapter extends BaseObject{
private Object1_class2 oc2;
public Object2Adapter(Object1_class2 oc2) {
this.oc2 = oc2;
}
@Override
public String getName() {
//把请求委托给oc2
return oc2.getName(false);
}
}
在适配器器类中有一个Object1_Class2类型的变量,这就是我们要适配的对象。适配器类相当于一个大的包装盒,它把项目1的类包装成了项目2的类,在调用相应方法时在方法内部调用适配对象的方法,委托请求。这样就让项目1的类无缝融入到了项目2中。
来测试一下吧。
public class MainTest {
public static void main(String[] args) {
//假设注册管理器就是一个集合
ArrayList<BaseObject> list= new ArrayList<>();
list.add(new Obejct2_Class1());
//通过适配器项目1的类也可以加入进来了
list.add(new Object2Adapter(new Object1_class2()));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getName());
}
}
}
测试成功,项目1的对象也可以进入注册管理器并被统一调用方法了。
3.适配器模式小结
还是老话,适配器就是通过包装和组合让一个不相干的类能被一视同仁的使用。在写法上,适配器模式和装饰者模式很像,都是继承父类,组合新类。但是两个模式的目的是不一样的,装饰者模式是为了增强功能而包装对象,适配器模式是为了改变外观而包装对象,没有增强功能的行为。
在实际开发中,如果想要一视同仁的利用多态使用两个不同继承结构的对象,那么就用适配器模式吧。