Оптимизация кода с лямбда выражениями. DRY

302
24 января 2017, 22:04

В общем есть такой код:

private static final Map<Integer, Constrain<CharSequence>>
        minLengthCache = new HashMap<>(),
        maxLengthCache = new HashMap<>();
public static Constrain<CharSequence> minLength(int length) {
    Constrain<CharSequence> cached = minLengthCache.get(length);
    if (cached == null)
        minLengthCache.put(length, cached = string -> string.length() > length);
    return cached;
}
public static Constrain<CharSequence> maxLength(int length) {
    Constrain<CharSequence> cached = maxLengthCache.get(length);
    if (cached == null)
        maxLengthCache.put(length, cached = string -> string.length() < length);
    return cached;
}

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

Первым делом приходит в голову нечто такое:

public static Constrain<CharSequence> minLength(int length) {
    return cachedOrNew(string -> string.length() > length);
}
public static Constrain<CharSequence> cachedOrNew(Constrain<CharSequence> newObj) {
    Constrain<CharSequence> cached = minLengthCache.get(length);
    if (cached == null)
        minLengthCache.put(length, cached = newObj);
    return cached;
}

Но здесь теряется смысл в кэше совсем. Ведь каждый раз всё равно будет создаваться новый экземпляр объекта, а заодно и его класс, объекта, который должен быть возвращен, если в кэше такого нет.

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

Answer 1

В общем решил проблему вот так:

private interface ConstrainFactory<C, P> {
    Constrain<C> create(P param);
}
private static <P, C> Constrain cachedOrNew(Map<P, Constrain<C>> cache, ConstrainFactory factory, P param) {
    Constrain cached = cache.get(param);
    if (cached == null)
        cache.put(param, cached = factory.create(param));
    return cached;
}
public static Constrain<CharSequence> minLength(int length) {
    return cachedOrNew(minLengthCache, minLengthConstrain, length);
}
private static ConstrainFactory<String, Integer> minLengthConstrain = (length) -> (string) -> string.length() > length;

Всё решение основывается на том, что есть некий параметр, на основе которого можно генерировать классы. Для меня сойдет, но возможности лямбды по сути не используются, да и выглядит код своебразно - сразу и не въедешь, для чего что нужно. Поэтому вопрос оставляю открытым - может кто покрасивее предложит решение.

READ ALSO
JavaFX Как узнать координаты курсора, который находится в TextField?

JavaFX Как узнать координаты курсора, который находится в TextField?

Нашел только getCaretPosition(), но это немного не то

667
JavaFX - при вызове функций, которые долго выполняются, происходит ошибка &ldquo;Платформа Java не работает &rdquo;

JavaFX - при вызове функций, которые долго выполняются, происходит ошибка “Платформа Java не работает ”

Здравствуйте, пишу приложение на javaВ качестве GUI использую JavaFX (скажу сразу, что при использование swt данной проблемы нет)

284
Как оперировать шириной .navbar-brand в Bootstrap?

Как оперировать шириной .navbar-brand в Bootstrap?

Есть такой навбар, сайдбар и контент:

346
Не работает скрипт после добавления append()

Не работает скрипт после добавления append()

Помогите разобраться, может что то упускаю из виду

291