Java8: как вызвать метод для переданного типа

Я пытаюсь реализовать шаблон декоратора, моя проблема в том, что у меня есть разные сгенерированные источники, которые будут переданы декорированному маскеру, у меня нет общего родителя, который предоставляет методы, которые мне нужны для выполнения различных маскировок в каждом маскировщике, поэтому для решения этой проблемы я подумал о передаче типа маскеру, и каждый маскер будет знать сеттер / получатель, который он будет использовать, теперь я хочу передать объекты, у которых есть общий родитель (без методов), и преобразовать эти объекты, используя переданный тип , теперь моя проблема заключается в вызове получателя, например для NumbrMasker, я знаю, что получателем / установщиком будет getNumber / setNumber, но я не уверен, как вызывать методы для переданного типа.

class NumberDecoratedMasker extends Masker {

private Class classType;

public DecoratedMasker (Masker masker, Class classType) {      
       this.classType = classType;
}

//for Number masker
public void mask(ParentModel parent) {
   //cast parent using classtype
   //call getNumber/setNumber for masking number

   if (masker != null)
      makser.mask(parent); // this is the decorated call for the other masker in the decorator structure
}
}


class ParentModel {
 //has nothing
}

class Elementa extends ParentModel {
  //has setters and getters for number
}

Теперь я инициализирую Decorated с помощью classType объекта, который хочу замаскировать.

 Masker masker = new NumberDecoratedMakser(new SecondNumberDecoratedMasker(ElementA.class), ElementA.class);

ParentModel model = new ElementA();
masker.mask(moel);

Я знаю, что отражение будет решением в этом случае, но я не могу с этим согласиться, есть ли способ сделать это с помощью java8?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
79
1

Ответы 1

public void mask(ParentModel parent, Supplier<ParentModel> getter,
                                     Consumer<ParentModel> setter) {
    setter.accept(parent);
    parent = getter.get();
}

Для использования класса потребовалось бы что-то вроде уродливый:

interface Xetter<T> {
    void set(T x);
    T get();
}

public void mask(ParentModel parent, Class<Xetter<ParentModel>> xetter) {
}

Лучше было бы использовать ... классы свойств, используемые в JavaFX, например StringProperty. Это обертывает тип / класс значения и обеспечивает абстракцию, которую вы, похоже, ищете. Посмотрите на WritableValue.

В качестве последнего замечания. В общем, следует использовать классы с параметризацией, например:

public <T> T f(Class<T> type, Object value) {
    return type.cast(value);
}

После отзыва: Все еще не совсем уверен, что украшение соответствует предполагаемому поведению.

class Value {
}

class NumberValue extends Value {
    private Number number;
    void setNumber(Number number) {
        this.number = number;
    }
    Number getNumber() {
        return number:
    }
}

class Masker {
    public void mask(Value value) {
    }
}   

Либо

class NumberDecoratedMasker<T extends NumberValue> extends Masker {
    private final Masker masker;
    private final Class<T> type;

    public NumberDecoratedMasker(Masker masker, Class<T> type) {
        this.masker = masker;
        this.type = type;
    }

    //for Number masker
    public void mask(Value value) {
        //cast parent using classtype
        //call getNumber/setNumber for masking number
        NumberValue n = type.cast(value);
        n.setNumber(42 + n.getNumber);
        value = n;
        if (masker != null) {
            masker.mask(value);
        }
    }
}
Masker masker = new NumberDecoratedMasker(
    new SecondNumberDecoratedMasker<NumberValue>(NumberValue.class), NumberValue.class);

или же

class NumberDecoratedMasker extends Masker {
    private final Masker masker;
    private final Class<NumberValue> type;

    public NumberDecoratedMasker(Masker masker, Class<NumberValue> type) {
        this.masker = masker;
        this.type = type;
    }

    //for Number masker
    public void mask(Value value) {
        //cast parent using classtype
        //call getNumber/setNumber for masking number
        NumberValue n = type.cast(value);
        n.setNumber(42 + n.getNumber);
        value = n;
        if (masker != null) {
            masker.mask(value);
        }
    }
}
Masker masker = new NumberDecoratedMasker(
    new SecondNumberDecoratedMasker(NumberValue.class), NumberValue.class);

Value model = new NumberValue();
masker.mask(model);

спасибо за ваш ответ, за ваше первое предложение, означает ли это, что мне нужно отправить лямбду с помощью setter / getter в метод? Я не могу понять ваше второе предложенное решение, не могли бы вы предоставить более подробную информацию. также, как я уже упоминал, это предназначено для декорирования метода, что означает, что у меня есть ссылка на другой маскер, который также будет вызывать маску внутри моего метода, я отредактировал вопрос, чтобы он был более ясным

Amer Qarabsa 21.03.2018 12:51

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

Joop Eggen 21.03.2018 14:16

Я добавил более подробный пример своего сценария, надеюсь, он более понятен

Amer Qarabsa 21.03.2018 14:55

внутри маскера я не должен знать о NumberValue, я знаю, что тип coming может иметь метод setNumber / getNumber, но я не знаю о самом типе, поэтому может быть еще один дочерний элемент для parentModel, который также имеет разные сеттеры, о которых мы знаем, поэтому мы создаем другую украшенную маску, которая может вызывать эти методы

Amer Qarabsa 21.03.2018 15:59

Затем нужен интерфейс (как у моего Xetter) для предоставления setNumber и getNumber. Я предлагаю вам сначала попробовать разработать прототип, прежде чем код станет слишком замысловатым.

Joop Eggen 21.03.2018 16:02

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

Amer Qarabsa 21.03.2018 16:06

Лучше проверить интерфейсы if (x instanceof Ifc) { ((Ifc)x).setNumber(13); }

Joop Eggen 21.03.2018 16:19

Другие вопросы по теме