Java Filter Factory实现

问题描述 投票:1回答: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"
            }
        };
    }

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

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

java design-patterns refactoring factory-pattern filefilter
1个回答
1
投票

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

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);
    }
}

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

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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.