一.什么是适配器模式🍓
适配器模式是一种结构型设计模式,它将一个类的接口转换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够协同工作。这种模式的主要目的是提高代码的可重用性和可维护性。
适配器模式的工作原理是通过创建一个适配器类,该类包含一个源接口和一个目标接口。适配器类将客户端请求转换为源接口可以理解的命令,并执行相应的操作。这样,客户端只需要与适配器交互,而不需要直接与源接口交互,从而实现了接口的转换和适配。
适配器模式的应用场景通常包括已经存在的类,其方法和需求不匹配的情况。通过适配器模式,可以将不同的接口统一起来,使得原本无法协同工作的类能够一起工作。例如,电源适配器和USB转接头都是适配器模式的实际应用例子。
适配器模式主要分为三类:类适配器模式、对象适配器模式和接口适配器模式。类适配器模式通过继承源类和实现目标接口来实现适配,而对象适配器模式则通过组合源对象和实现目标接口来达到适配的目的
一.类适配器🌺:
Adpter是具体的适配器既实现了目标接口Target,又继承了目前要适配的类Adaptee。
例子一:
一个接口:官方输出方式
两个类:我的输出方式和输出适配器。
目的:将我的输出方式通过适配器转换成三种官方输出,分别是大写,小写,ASCII码。
UML图如下:
PrintAdapter.java
package 二十三种设计模式之适配器模式;public class PrintAdapter extends MyPrint implements OfficialPrint{PrintAdapter(String words) {super(words);// TODO Auto-generated constructor stub}@Overridepublic void ToUpperChar() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.toUpperCase(word));}}@Overridepublic void ToLowerChar() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.toLowerCase(word));}}@Overridepublic void ToASCII() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.getNumericValue(word));}}}
OfficialPrint.java
package 二十三种设计模式之适配器模式;public interface OfficialPrint {
void ToUpperChar();
void ToLowerChar();
void ToASCII();
}
MyPrint.java
package 二十三种设计模式之适配器模式;public class MyPrint {
private String Words;
MyPrint(String words){Words=words;
}
String getWords() {return Words;
}
}
user.java
package 二十三种设计模式之适配器模式;public class user {public static void main(String []args) {OfficialPrint printadapter=new PrintAdapter("HEllo Word!");printadapter.ToLowerChar();System.out.println("\n");printadapter.ToUpperChar();System.out.println("\n");printadapter.ToASCII();}
}
输出结果:
这里思考一个小问题:为啥,User类中
OfficialPrint printadapter=new PrintAdapter("HEllo Word!");不写成
PrintAdapter printadapter=new PrintAdapter("HEllo Word!");呢?
参考答案:
这是想强调“只使用OfficialPrint接口”的方法。OfficialPrint和PrintAdapter接口对外提供的方法是相同的。但在有些情况下,PrintAdapter类中的方法比OfficialPrint类中的方法多。通过将对象保存在OfficialPrint中并使用该变量,可以明确地表明程序的意图,即并不是使用PrintAdapter中的方法,而是OfficialPrint中的方法。
看完下面的例子二,你就会更加理解这个问题的答案了。🙂
例子二:
在上面的结构中增加一个encryptionPrint类,要求通过PrintAdapter加密输出。
UML图如下:
PrintAdapter.java
package 二十三种设计模式之适配器模式;public class PrintAdapter extends MyPrint implements OfficialPrint,encryptionPrint{PrintAdapter(String words) {super(words);// TODO Auto-generated constructor stub}@Overridepublic void ToUpperChar() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.toUpperCase(word));}}@Overridepublic void ToLowerChar() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.toLowerCase(word));}}@Overridepublic void ToASCII() {// TODO Auto-generated method stubfor(int i=0;i<getWords().length();i++) {char word=getWords().charAt(i);System.out.print(Character.getNumericValue(word));}}@Overridepublic void Encrypt() {// TODO Auto-generated method stubString originalString=getWords();String replaceString=originalString.replace(originalString,"**********");System.out.println(replaceString);}}
user.java
package 二十三种设计模式之适配器模式;public class user {public static void main(String []args) {encryptionPrint encryptionprint=new PrintAdapter("HEllo Word!");encryptionprint.Encrypt();}
}
输出结果:
二.对象适配器🍉:
对象适配器模型
这里的Adapter与上面的不同,是采用继承Target抽象类,包含Adaptee对象的方式来实现Adaptee适配Target的。
例子:将上面例子一用对象适配器来实现
UML图如下
和上面的要求一致,用对象适配器方式实现只需要改Adapter和Target就可以了。
PrintAdapter.java
package 二十三种设计模式之适配器模式;public class PrintAdapter extends OfficialPrint{private MyPrint myprint;
PrintAdapter(String s){myprint=new MyPrint(s);
}@Overridepublic void ToUpperChar() {// TODO Auto-generated method stubfor(int i=0;i<myprint.getWords().length();i++) {char word=myprint.getWords().charAt(i);System.out.print(Character.toUpperCase(word));}}@Overridepublic void ToLowerChar() {// TODO Auto-generated method stubfor(int i=0;i<myprint.getWords().length();i++) {char word=myprint.getWords().charAt(i);System.out.print(Character.toLowerCase(word));}}@Overridepublic void ToASCII() {// TODO Auto-generated method stubfor(int i=0;i<myprint.getWords().length();i++) {char word=myprint.getWords().charAt(i);System.out.print(Character.getNumericValue(word));}}}
OfficialPrint.java
package 二十三种设计模式之适配器模式;public abstract class OfficialPrint {
public abstract void ToUpperChar();
public abstract void ToLowerChar();
public abstract void ToASCII();
}
三.为什么要使用适配器?
适配器适合用在版本升级的情况下。新版本扮演Adaptee,旧版本扮演Target,编写一个Adapter,让它使用新版本的类来实现旧版本的方法,从而达到升级更新的作用。