结构型模式
设计模式按照大的分类,分为结构型设计模式、行为型设计模式和创建型设计模式。
结构型设计模式是一种考虑如何将类和对象结合在一起,从而形成一个更大的结构。它描述两种不同的事物:类和对象,根据这一点,可分为类结构型和对象结构型模式。
类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系;
对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式
结构型模式之一适配器模式
什么是适配器模式
适配器模式,名字来源于生活中的适配器,如下图:
适配器
所以,它的功能和适配器相同,在一个方法 A 中,通过调用另外方法 B,从而在 A 中实现 B 的功能。
为什么要有适配器模式?就像上面的图一样,有的时候,我们需要的功能是一个三孔的插座,而面前只有一个两孔的插座,那就做一个适配器,它能够插入三孔的插座,同时对外又能提供一个两孔的插口,即:它在两孔的插口上,调用了三孔插口的功能。
上面说的是,为什么要用适配器模式,其实这也是适配器模式的功能和原理。
适配器模式的实现
适配器模式的实现,主要分为三个部分:
两孔的插座;
适配器;
三孔的插座。
从上面原理中,也可以看出,两孔插座和适配器实现同一个接口,而适配器中,需要调用三孔插座的方法。
三孔插座
三孔插座,需要提供一个接口,如下:
/**
- 三孔插座接口
*/
public interface ThreeHolePlug {
//三孔插座的功能
void threeHole();
}
三孔插座的实现类,需要实现这个接口:
/**
- 三孔插座实现类
*/
public class ThreeHoleImpl implements ThreeHolePlug {
@Override
public void threeHole() {
System.out.println("执行三孔插座的功能");
}
}
而我们在适配器里,就需要调用这个方法。
有的人可能要问,三孔插座为什么不直接是一个类,非要实现一个接口?
这是为了提供扩展性,比如,如果我们需要实现两孔-四孔的适配器,两孔-五孔的适配器,都可以通过实现这个接口去扩展。
适配器类
适配器和两孔插座实现了同一个接口,就像上面说的,适配器和两孔插座,都需要提供一个两孔的插口:
/**
- 两孔插座接口
*/
public interface TwoHolePlug {
//要求两孔插座支持三孔插头的插入
void twoHole(int holeNum);
}
那么看下,适配器是怎么去实现三孔插座的功能:
/**
- 适配器
*/
public class Adapter implements TwoHolePlug{
//三孔插座
private ThreeHolePlug threeHolePlug;
//通过调用三孔插座的接口,将两孔插座转为三孔插座
@Override
public void twoHole(int holeNum) {
//当需要实现三孔插座的功能时
if (3 == holeNum) {
//初始化三孔插座的实现类
threeHolePlug = new ThreeHoleImpl();
//让三孔插座去实现功能
threeHolePlug.threeHole();
}
}
}
可以看到,适配器在两孔的方法的内部,根据传入的孔的数量,调用了三孔的实现。这样就完成了两孔插座到三孔插座的适配。
两孔插座
适配器只负责处理两孔到三孔的转换,两孔的功能,还需要两孔插座自己实现:
/**
- 两孔插座的实现
*/
public class TwoHolePlugImpl implements TwoHolePlug {
//适配器
private TwoHolePlug adapter;
@Override
public void twoHole(int holeNum) {
//自己能执行的功能
if (2 == holeNum) {
System.out.println("执行两孔插座的功能");
}
//不能执行的,通过适配器去调用三孔插座来实现功能
if (3 == holeNum) {
adapter = new Adapter();
adapter.twoHole(holeNum);
}
}
}
这段代码里,先判断要求的功能,如果是两孔自己能搞定的,自己去实现,否则,调用适配器去帮助实现。
主函数
最后,通过主函数验证下功能:
public class main {
//主函数
public static void main(String[] args) {
TwoHolePlug twoHolePlug = new TwoHolePlugImpl();
//实现两孔插座的功能
twoHolePlug.twoHole(2);
//实现三孔插座的功能
twoHolePlug.twoHole(3);
}
}
看下打印结果:
打印结果
结果中,当需要两孔插座的功能时,能够得到,当需要三孔插座的功能时,也能够满足,符合预期。