1

受 FilenameFilter.java 的启发,我想使用类似的方法/设计模式来解决我的问题。我从 sftp 服务器中选择了基于以下内容的文件:

  1. 如果超过 n 天
  2. 如果它早于 n 天并且它的名称是某种模式。

我已经定义了一个功能接口 SemanticFileFilter 如下:

public interface SftpFileFilter
{
    boolean accept(LsEntry sftpFile);
}

sftp 的 LsEntry 基本上类似于 java 中的 File。

想要定义 SftpFileFilterFactory 以在一个地方获取 SftpFileFilter 的所有实现,如下所示:

    public class SftpFileFilterFactory 
    {
        public static final SftpFileFilter OLD_FILE_FILTER =  new SftpFileFilter()
        {
//ERROR: because Interface function method should take only 1 parameter
            //@Override
            public boolean accept(LsEntry lsEntry,int nDays)
            {
                //checks if files if older than nDays
            }
        };

        public static final SftpFileFilter PATTERN_MATCH_OLD_FILE_FILTER =  new SftpFileFilter()
        {
//ERROR: because Interface function method should take only 1 parameter
            //@Override
            public boolean accept(LsEntry lsEntry,int nDays, String pattern)
            {
                //checks if files if older than nDays and matches pattern "pattern"
            }
        };
    }

如何设计我的接口的函数方法或工厂实现,以便将来如果需要定义更多类似的过滤器,我不需要在代码更改上费心,只需定义新的过滤器。

我们也应该能够链接过滤器。也就是说,为旧文件定义一个过滤器,为模式匹配定义另一个过滤器。如果两者都需要使用,它们应该能够链接在一起,因此两者都可以使用。

4

1 回答 1

1

您的问题提醒Command设计模式。您需要实现不同的条件并提供其他参数,您可以使用构造函数并创建类或使用Java 8lambda 表达式。请参见下面的示例:

import java.util.ArrayList;
import java.util.List;

public class DesignPatterns {

    public static void main(String[] args) {
        List<SftpFileFilter> filters = new ArrayList<>();
        filters.add(new OlderThanNDaysFilter(10));
        filters.add(new NameSftpFileFilter("tmp.txt"));
        // you can use lambda as well
        filters.add((file) -> file.getName().length() > 0);
    }
}

interface SftpFileFilter {
    boolean accept(LsEntry sftpFile);
}

class OlderThanNDaysFilter implements SftpFileFilter {

    private final int days;

    public OlderThanNDaysFilter(int days) {
        this.days = days;
    }

    @Override
    public boolean accept(LsEntry sftpFile) {
        return sftpFile.isOlder(days);
    }
}

class NameSftpFileFilter implements SftpFileFilter {

    private final String name;

    public NameSftpFileFilter(String name) {
        this.name = name;
    }

    @Override
    public boolean accept(LsEntry sftpFile) {
        return sftpFile.getName().equals(name);
    }
}

这些对象太小,不需要为它创建工厂。如有必要,您可以创建和使用它们。当然,您可以创建创建一些预定义过滤器的工厂:

class ConditionFactory {
    private static final SftpFileFilter OLDER_THAN_TEN = new OlderThanNDaysFilter(10);
    private static final SftpFileFilter PASSWORDS_FILE = new NameSftpFileFilter("passwords.txt");

    public SftpFileFilter createOlderThan10Days() {
        return OLDER_THAN_TEN;
    }

    public SftpFileFilter createPasswordsFile() {
        return PASSWORDS_FILE;
    }

    public SftpFileFilter createNameFilter(final String name) {
        return new NameSftpFileFilter(Objects.requireNonNull(name));
    }

    public SftpFileFilter createOlderThan(final int days) {
        return new OlderThanNDaysFilter(days);
    }
}

这是过滤器实现和客户端代码之间的良好分离,客户端代码不知道如何实现按名称过滤并且可以轻松交换。

Java 8您可以java.util.function.Predicate直接使用或通过您的界面扩展它:

interface SftpFileFilter extends Predicate<LsEntry> {
    boolean accept(LsEntry sftpFile);

    @Override
    default boolean test(LsEntry lsEntry) {
        return accept(lsEntry);
    }
}
于 2019-04-09T10:24:13.330 回答