本文共 5913 字,大约阅读时间需要 19 分钟。
使用者依赖的接口与提供者的接口不匹配时,就加一层适配,而不修改两端的代码
生活中使用的风扇,假设插头是两孔的,但是我们家里墙上的插座只有三孔的,这个时候就需要一个适配器了,这个适配器就是外面买的插座,以上场景为例,写一个例子:三孔的插座:
public class ThreeOutlet { /** 三孔插座 */ public void link(String positive, String negative, String earthWire) { System.out.println(String.format("多一根地线,保证安全用电:%s %s %s", positive, negative, earthWire)); }}
我们使用电风扇需要启动和关闭的接口:
public interface TwoOutlet { /** 启动 */ void power(String positive, String negative); /** 关闭 */ void shutDown();}
适配插座,外面买来的,可以使用两孔的、三孔的:
public class Adapter1 extends ThreeOutlet implements TwoOutlet { private String ew = "多一根地线"; // 私有内置地线 @Override public void power(String positive, String negative) { link(positive, negative, ew); } @Override public void shutDown() { System.out.println("拔掉插头"); } @Override public void link(String positive, String negative, String earthWire) { super.link(positive, negative, earthWire); }}
电风扇类:
public class Fanner { private TwoOutlet outlet; public void run() { outlet.power("1", "0"); System.out.println("获得动力"); System.out.println("风扇运转"); outlet.shutDown(); System.out.println("关闭电力,风扇停止运转"); } public void setOutlet(TwoOutlet outlet) { this.outlet = outlet; }}
测试类:
public class Test { public static void main(String[] args) { Fanner fanner = new Fanner(); Adapter1 adapter1 = new Adapter1(); fanner.setOutlet(adapter1); fanner.run(); }}类图:
把一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的
优点:
缺点:
类图:
涉及到的角色:类的适配器模式的结构:
Target接口:public interface Target { /** 源类也有的方法 */ void sampleOperation1(); /** 源类没有的方法 */ void sampleOperation2();}
Adaptee源角色:
public class Adaptee { public void sampleOperation1(){ System.out.println("源类也有的方法"); }}
Adapter适配器角色:
public class Adapter extends Adaptee implements Target { /** 源类和目标类都有的方法 */ @Override public void sampleOperation1() { super.sampleOperation1(); } /** 源类没有的方法,期望有这个方法 */ @Override public void sampleOperation2() { }}
对象的适配器模式的结构:
Target接口:public interface Target { /** 源类也有的方法 */ void sampleOperation1(); /** 源类没有的方法 */ void sampleOperation2();}
Adaptee源角色:
public class Adaptee { public void sampleOperation1(){ System.out.println("源类也有的方法"); }}
Adapter适配器角色:
public class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } /** 源类和目标类都有的方法 */ @Override public void sampleOperation1() { this.adaptee.sampleOperation1(); } /** 源类没有的方法,期望有这个方法 */ @Override public void sampleOperation2() { System.out.println("适配一个方法"); }}
需要注意的是,适配器不是在开始设计的时候用的,而是在解决现有的项目中的问题
赵高指鹿为马的故事都应该听说过,下面以适配器模式做个小例子:
现在需要的是一匹马:
public interface NeedHorse { /** 需要一匹马 */ void needHorse();}
但是有的是一只鹿:
public class DeerAdaptee { public void deer() { System.out.println("我是一头鹿,有人要指鹿为马!"); }}
把鹿适配为马,指鹿为马:
public class DeerChangeAdapter implements NeedHorse { private DeerAdaptee deerAdaptee; public DeerChangeAdapter(DeerAdaptee deerAdaptee) { this.deerAdaptee = deerAdaptee; this.deerAdaptee.deer(); } public void deer() { System.out.println("我是一头鹿,有人要指鹿为马!"); } @Override public void needHorse() { System.out.println("我是一匹马(其实我的真实身份是一只鹿)"); }}
测试类:
public class Test { public static void main(String[] args) { System.out.println("这个是鹿还是马?"); DeerAdaptee adaptee = new DeerAdaptee(); DeerChangeAdapter adapter = new DeerChangeAdapter(adaptee); adapter.needHorse(); }}类图:
古有指鹿为马,现有指方为圆,nice:
我们需要的是一个球:public interface BallIF { /** 计算体积 */ Double calculateVolume(); /** 计算面积 */ Double calculateAcreage(); /** 半径取值 */ Double getRadius(); /** 半径赋值 */ Double setRadius(double radius);}
现在有的是一个立方体:
public class Cube { private Double width; public Cube(Double width) { this.width = width; } /** 计算体积 */ public Double calculateVolume() { return width * width * width; } /** 计算面积 */ public Double calculateAcreage() { return width * width; } /** 长度取值 */ public Double getWidth() { return width; } /** 长度赋值 */ public void setWidth(Double width) { this.width = width; }}
适配器适配一下,指方为圆:
public class MagicFinger implements BallIF { private double radius = 0; private static double PI = 3.14d; private Cube adaptee; public MagicFinger(Cube adaptee) { super(); this.adaptee = adaptee; radius = this.adaptee.getWidth(); } @Override public Double calculateVolume() { return (4.0d/3.0d) * PI * (radius * radius); } @Override public Double calculateAcreage() { return PI * 4.0d * (radius * radius * radius); } @Override public Double getRadius() { return radius; } @Override public Double setRadius(double radius) { return this.radius = radius; }}
测试一下:
public class Test { public static void main(String[] args) { Cube cube = new Cube(2.0); MagicFinger finger = new MagicFinger(cube); System.out.println("半径:" + finger.getRadius()); System.out.println("体积:" + finger.calculateVolume()); System.out.println("面积:" + finger.calculateAcreage()); }}类图:如果想有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式
转载地址:http://hoiuz.baihongyu.com/