适配器模式的用途
在实际代码编写中,我们可能会在一个地方用到两种不同类型但是功能相同的类,为了能够统一调用,我们可以用一个适配器类继承一个类型的接口去委托的执行实际的另一个类型的类的功能,从而完成不同类型之间的适配功能。
基本构成
由UML图我们可以看到,适配器模式的大致思想:
要想让两个不同类型的类相匹配,我们只需实现其中一个类的接口,在其中代理另外一个类即可。这种继承和代理的巧妙运用就能让程序兼容性更好。
例子:插头转换器
这里有一个非常形象的例子——插头的转换器:
不同国家的插头标准不同,在国外想使用国标的插头,必须要通过一个适配器来实现,下面我们就用代码来模拟这样的一个场景:
在一座俄罗斯旅馆:
class RussianHotel
{
RussianSocket rs;
RussianHotel(RussianSocket rs)
{
this.rs = rs;
}
public void charge() {
rs.charge();
}
}
旅馆的实例化需要一个俄标插头来实现,因此我们再编写俄标插头的接口和实现:
interface RussianSocket
{
void charge();
}
class RussianSocketimpl implements RussianSocket
{
@Override
public void charge() {
System.out.println("use RussianSocket charge!");
}
}
如此,俄罗斯本地人在旅馆充电的操作可以理解为:
public static void main(String[] args) {
RussianSocket rs = new RussianSocketimpl();
RussianHotel rh = new RussianHotel(rs);
rh.charge();
}/* Output:
use RussianSocket charge!
*///:~
现在我们只有国标插头:
interface ChineseSocket
{
void charge();
}
class ChineseSocketimpl implements ChineseSocket
{
@Override
public void charge() {
System.out.println("use ChineseSocket charge!");
}
因此我们需要一个适配器来将国标转化为俄标:
class Adapter implements RussianSocket{
private ChineseSocket cs;
Adapter(ChineseSocket cs) {
this.cs = cs;
}
@Override
public void charge() {
cs.charge();
}
}
可以看到适配器通过实现俄标接口,代理国标插口即可实现。
下面模拟在旅馆使用适配器的情况:
public static void main(String[] args) {
ChineseSocket cs = new ChineseSocketimpl();
RussianSocket ad = new Adapter(cs);
RussianHotel rhad = new RussianHotel(ad);
rhad.charge();
}/* Output:
use ChineseSocket charge!
*///:~
通过一个适配器完成插座的转换。
这个例子用真实的适配器形象的描述了适配器模式的运行流程。
总结
适配器模式的要点就是:
- 对原有接口的实现
- 适配器对象组合另一个接口的对象
- 对原有接口的方法通过委托另一个对象实现
从中我们也能看出DIP原则的重要性,具体应该依赖于抽象,通过抽象接口建立联系能有效隔离与具体实现的直接接触。