【问题标题】:Java Filter Factory implementationJava过滤器工厂实现
【发布时间】:2019-08-30 08:54:22
【问题描述】:

受 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】:

    您的问题提醒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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 2012-10-12
      • 1970-01-01
      相关资源
      最近更新 更多