欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式(Java)—Adapter模式

程序员文章站 2024-03-17 22:48:04
...

一、适配器的角色
在程序的世界中,经常会存在现有的程序无法直接使用,需要做适当的变换之后才能使用的情况。这种用于填补“现有程序”和“所需程序”之间的差异的设计模式就是Adapter模式。

Adapter模式有以下两种:
1.类适配器模式(使用继承的适配器)
2.对象适配器模式(使用委托的适配器)

二、使用继承的适配器
示例程序:将输入的字符串显示为(Hello)或是Hello的简单程序。
设计模式(Java)—Adapter模式

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语言中,委托就是指将某个方法中的实际处理交给其他实例的方法。
设计模式(Java)—Adapter模式

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方法。

设计模式(Java)—Adapter模式

示例:
使用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();
        }
    }

}