Я пытаюсь реализовать шаблон декоратора, моя проблема в том, что у меня есть разные сгенерированные источники, которые будут переданы декорированному маскеру, у меня нет общего родителя, который предоставляет методы, которые мне нужны для выполнения различных маскировок в каждом маскировщике, поэтому для решения этой проблемы я подумал о передаче типа маскеру, и каждый маскер будет знать сеттер / получатель, который он будет использовать, теперь я хочу передать объекты, у которых есть общий родитель (без методов), и преобразовать эти объекты, используя переданный тип , теперь моя проблема заключается в вызове получателя, например для 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?




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);
Хорошо, что вы уточнили в своем вопросе немного больше. Тем не менее мне не совсем понятно, как связаны ParentModel и Class, что они означают и как используются вместе. Отсюда мой расплывчатый ответ. Вы можете привести более полный пример того, как оформленный использует оба параметра и что может делать ваш декоратор.
Я добавил более подробный пример своего сценария, надеюсь, он более понятен
внутри маскера я не должен знать о NumberValue, я знаю, что тип coming может иметь метод setNumber / getNumber, но я не знаю о самом типе, поэтому может быть еще один дочерний элемент для parentModel, который также имеет разные сеттеры, о которых мы знаем, поэтому мы создаем другую украшенную маску, которая может вызывать эти методы
Затем нужен интерфейс (как у моего Xetter) для предоставления setNumber и getNumber. Я предлагаю вам сначала попробовать разработать прототип, прежде чем код станет слишком замысловатым.
да, это было бы простое решение, проблема в том, что мои модели создаются автоматически, поэтому у меня нет этой опции, поэтому я подумал, может быть, есть способ сделать это, кроме отражения, в любом случае спасибо
Лучше проверить интерфейсы if (x instanceof Ifc) { ((Ifc)x).setNumber(13); }
спасибо за ваш ответ, за ваше первое предложение, означает ли это, что мне нужно отправить лямбду с помощью setter / getter в метод? Я не могу понять ваше второе предложенное решение, не могли бы вы предоставить более подробную информацию. также, как я уже упоминал, это предназначено для декорирования метода, что означает, что у меня есть ссылка на другой маскер, который также будет вызывать маску внутри моего метода, я отредактировал вопрос, чтобы он был более ясным