MST
星途 面试题库

面试题:Java基础类设计中代理模式的深度理解与应用

在Java基础类的设计场景下,如I/O流相关类,如何利用代理模式来实现功能增强,比如日志记录或者权限控制?请详细描述实现思路并给出关键代码示例。
17.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 定义接口:对于I/O流相关类,它们通常实现了一些标准接口,如InputStreamOutputStream等。我们可以基于这些接口来创建代理。
  2. 创建真实主题类:即实际的I/O流类,例如FileInputStreamFileOutputStream等。
  3. 创建代理类:代理类实现与真实主题类相同的接口,并持有一个真实主题类的引用。在代理类的方法中,先进行功能增强操作(如日志记录、权限控制),然后调用真实主题类的相应方法。

关键代码示例

  1. InputStream为例
    • 定义代理类
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

public class LoggingInputStream extends FilterInputStream {
    private static final Logger logger = Logger.getLogger(LoggingInputStream.class.getName());

    public LoggingInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        logger.info("About to read a byte.");
        int result = super.read();
        logger.info("Read a byte: " + result);
        return result;
    }

    @Override
    public int read(byte[] b) throws IOException {
        logger.info("About to read " + b.length + " bytes.");
        int result = super.read(b);
        logger.info("Read " + result + " bytes.");
        return result;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        logger.info("About to read " + len + " bytes starting from offset " + off + ".");
        int result = super.read(b, off, len);
        logger.info("Read " + result + " bytes.");
        return result;
    }
}
- **使用代理类**:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) {
        try {
            InputStream fileInputStream = new FileInputStream("example.txt");
            InputStream loggingInputStream = new LoggingInputStream(fileInputStream);
            int data;
            while ((data = loggingInputStream.read()) != -1) {
                System.out.print((char) data);
            }
            loggingInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  1. 权限控制示例
    • 定义权限检查方法
public class PermissionChecker {
    public static boolean hasReadPermission() {
        // 实际应用中这里可能是复杂的权限检查逻辑,例如检查用户角色等
        return true;
    }
}
- **创建权限控制的代理类**:
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class PermissionControlledInputStream extends FilterInputStream {
    public PermissionControlledInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        if (!PermissionChecker.hasReadPermission()) {
            throw new SecurityException("You do not have permission to read.");
        }
        return super.read();
    }

    @Override
    public int read(byte[] b) throws IOException {
        if (!PermissionChecker.hasReadPermission()) {
            throw new SecurityException("You do not have permission to read.");
        }
        return super.read(b);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        if (!PermissionChecker.hasReadPermission()) {
            throw new SecurityException("You do not have permission to read.");
        }
        return super.read(b, off, len);
    }
}
- **使用权限控制代理类**:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class PermissionMain {
    public static void main(String[] args) {
        try {
            InputStream fileInputStream = new FileInputStream("example.txt");
            InputStream permissionControlledInputStream = new PermissionControlledInputStream(fileInputStream);
            int data;
            while ((data = permissionControlledInputStream.read()) != -1) {
                System.out.print((char) data);
            }
            permissionControlledInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            System.out.println(e.getMessage());
        }
    }
}