Реализация Java Filter Factory - PullRequest
       45

Реализация Java Filter Factory

1 голос
/ 09 апреля 2019

Вдохновленный FilenameFilter.java, я хочу использовать аналогичный подход / шаблон проектирования для решения моей проблемы. Я выбрал файлы с сервера sftp на основе:

  1. Если оно старше n дней
  2. Если он старше n дней и его имя определенным образом.

Я определил функциональный интерфейс SemanticFileFilter, как показано ниже:

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

LsEntry для sftp - это что-то вроде File in java.

Требуется определить 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"
            }
        };
    }

Как мне спроектировать метод функции или реализацию фабрики моего интерфейса так, чтобы в будущем, если нужно было определить аналогичные дополнительные фильтры, мне не пришлось бы сильно беспокоиться об изменениях кода, а просто определял новый фильтр.

Также мы должны быть в состоянии связать фильтры. То есть определите один фильтр для более старых файлов и другой для сопоставления с образцом. Если оба должны быть использованы, они должны быть в состоянии соединиться вместе и, следовательно, оба могут быть использованы.

1 Ответ

1 голос
/ 09 апреля 2019

Ваша проблема напоминает Command шаблон проектирования.Вам необходимо реализовать различные условия и предоставить дополнительные параметры, вы можете использовать конструкторы и создавать классы или использовать Java 8 лямбда-выражения.См. Пример ниже:

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