设计模式(Java)—Adapter模式
一、适配器的角色
在程序的世界中,经常会存在现有的程序无法直接使用,需要做适当的变换之后才能使用的情况。这种用于填补“现有程序”和“所需程序”之间的差异的设计模式就是Adapter模式。
Adapter模式有以下两种:
1.类适配器模式(使用继承的适配器)
2.对象适配器模式(使用委托的适配器)
二、使用继承的适配器
示例程序:将输入的字符串显示为(Hello)或是Hello的简单程序。
Banner类(实际情况类):
package Adapter1;
//适配器模式(类继承形式)
//此类为实际情况类,此类中实际上已经包含了对所要适配的情况的处理,但是执行需要使用接口调用,所以声明接口,间接的使用这些方法
public class Banner {
private String string;
//构造
public Banner(String string){
this.string = string;
}
public void showWithParen(){
System.out.println("("+string+")");
}
public void showWithAster(){
System.out.println("*"+string+"*");
}
}
Print接口(主程序调用功能的接口):
package Adapter1;
//声明外部调用接口,外部使用功能入口
public interface Print {
public abstract void printWeak();
public abstract void printStrong();
}
PrintBanner类(适配器)
package Adapter1;
//适配器类,继承实际情况类并且实现接口
//在有使用数据对象的情况需要使用继承类的方法
//在有使用方法的情况需要使用实现接口的方法
public class PrintBanner extends Banner implements Print {
public PrintBanner(String string) {
super(string);
// TODO Auto-generated constructor stub
}
@Override
public void printWeak() {
// TODO Auto-generated method stub
showWithParen();
}
@Override
public void printStrong() {
// TODO Auto-generated method stub
showWithAster();
}
}
Main类(主程序):
package Adapter1;
//主程序通过接口调用实现的功能,封装性好
//继承实现数据独立性
//接口实现功能独立性
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Print p = new PrintBanner("Hello");
p.printWeak();
p.printStrong();
}
}
总结:扮演适配器角色的是PrintBanner类。该类继承了Banner类并实现了“需求”–Print接口。PrintBanner类使用showWithParen方法实现了printWeak,使用showWithAster方法实现了printStrong,这样PrintBanner类就具有适配器的功能了。
注:主程序中将PrintBanner类的实例保存在了Print类型的变量中。在Main类中我们使用Print接口来进行编程的。对Main而言,Banner类、showWithParen方法和showWithAster方法完全被隐藏起来了。
三、使用委托的适配器
在Java语言中,委托就是指将某个方法中的实际处理交给其他实例的方法。
Main类和Banner类与继承方法完全相同,不过委托方式中的Print是类而不是接口。
Banner类(实际情况类):
package Adapter2;
public class Banner {
private String string;
public Banner(String string) {
this.string = string;
}
public void showWithParen() {
System.out.println("("+string+")");
}
public void showWithAster(){
System.out.println("*"+string+"*");
}
}
Print接口(主程序调用的接口):
package Adapter2;
public abstract class Print {
public abstract void printWeak();
public abstract void printStrong();
}
PrintBanner类(适配器):
package Adapter2;
public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String string) {
// TODO Auto-generated constructor stub
banner = new Banner(string);
}
@Override
public void printWeak() {
// TODO Auto-generated method stub
banner.showWithParen();
}
@Override
public void printStrong() {
// TODO Auto-generated method stub
banner.showWithAster();
}
}
Main类:
package Adapter2;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Print p = new PrintBanner("Hello");
p.printWeak();
p.printStrong();
}
}
总结:使用Banner实现一个Print类,该类中的方法与Print接口中的方法一致,由于Java中无法同时继承两个类,因此无法将PrintBannner类分别定义为Print类和PrintBanner类的子类。
PrintBanner类的banner字段中保存了Banner类的实例。该例是在PrintBanner类的构造中生成的,然后,printWeak方法和printStrong方法会通过banner字段调用Banner类的showWithParen和showWithAster方法。这样就形成了一种委托关系,当printBanner的printWeak被调用的时候,并不是PrintBanner类自己进行处理,而是将处理交给了其他实例(Banner类的实例)的showWithParen方法。
示例:
使用Adpter模式编写一个将属性保存至文件中的FileProperties类
FileIO接口:
package Adapter3_homework;
import java.io.*;
//文件功能调用接口
public interface FileIO {
public void readFromFile(String filename) throws IOException;
public void writeToFile(String filename) throws IOException;
public void setValue(String key,String value);
public String getValue(String key);
}
FileProperties类(适配器):
package Adapter3_homework;
import java.io.*;
import java.util.*;
//适配器(使用类继承的方法)
public class FileProperties extends Properties implements FileIO {
/**
*
*/
private static final long serialVersionUID = 1L;
//重写接口方法,在重写的接口功能中调用实际类的方法
@Override
public void readFromFile(String filename) throws IOException {
// TODO Auto-generated method stub
load(new FileInputStream(new File(filename)));
}
@Override
public void writeToFile(String filename) throws IOException {
// TODO Auto-generated method stub
store(new FileOutputStream(new File(filename)), "written by FileProperties");
}
@Override
public void setValue(String key, String value) {
// TODO Auto-generated method stub
setProperty(key, value);
}
@Override
public String getValue(String key) {
// TODO Auto-generated method stub
return getProperty(key,"");
}
}
Main类:
package Adapter3_homework;
import java.io.IOException;
public class Main {
//主程序通过接口调用已实现的功能,将实际类中的功能及方法隐藏
public static void main(String[] args) {
// TODO Auto-generated method stub
FileIO f = new FileProperties();
try{
//文件需要放在工程下面,而不是工程的子目录下,生成的文件也在工程目录下
f.readFromFile("file.txt");
f.setValue("year", "2004");
f.setValue("month", "4");
f.setValue("day", "21");
f.writeToFile("newfile.txt");
}catch(IOException e){
e.printStackTrace();
}
}
}