简体   繁体   English

Java 对象、更改字段侦听器、设计模式

[英]Java object, changed fields listener, design-pattern

There is a class:有一个类:

public class MyClass {
private String field1;
private String field2;
private String field3;
// getters, setters
}

Then we update some fields然后我们更新一些字段

MyClass myClass = new MyClass();
myClass.setField1("field1");
myClass.setField2(null);

How can I know which fields of MyClass were tried to be changed (invoked, in the example above field1 and field2)?我如何知道尝试更改 MyClass 的哪些字段(在上面的示例中调用 field1 和 field2)?
What is the best solution for that?什么是最好的解决方案? Maybe some design-pattern?也许一些设计模式?
One option is to create HashSet of changed fields for this object as an additional property and update it inside each setter but it does not seem nice.一种选择是为此对象创建已更改字段的HashSet作为附加属性,并在每个 setter 中对其进行更新,但这似乎不太好。
Should it be something like Proxy object which will be intercept all method calls (ie setXXX()) (through Java reflection?) or anything else?它应该是类似于 Proxy 对象的东西,它将拦截所有方法调用(即 setXXX())(通过 Java 反射?)或其他任何东西?

UPDATE更新
It seems that each setter should invoke some inner method what does not seem nice as I said.似乎每个 setter 都应该调用一些内部方法,正如我所说的那样,它看起来并不好。 And I don't need to notify any other objects about changes.而且我不需要通知任何其他对象有关更改。 I would like to store all states in this object and have access to these changes later.我想将所有状态存储在这个对象中,以后可以访问这些更改。
In details: if method setFieldX invoked then fieldX should be marked to be updated later详细说明:如果调用 setFieldX 方法,则应将 fieldX 标记为稍后更新
PS All fields have different names. PS 所有字段都有不同的名称。
Any other solutions except reflection (I want to populate object via pure setter)?除了反射之外的任何其他解决方案(我想通过纯 setter 填充对象)?

If you want to implement using conventional design-pattern approach, I would recommend using Observer Pattern如果您想使用传统的设计模式方法来实现,我建议使用观察者模式

Have a Listener for set field event of your class有一个侦听器用于您班级的设置字段事件

public interface FieldListener {

    public void fieldValueChanged(String fieldName, Object newValue);
}

Make a class implement this listener (Observer)让一个类实现这个监听器(观察者)

public class SampleObserver implements FieldListener {

    @Override
    public void fieldValueChanged(String fieldName, Object newValue) {
        System.out.println(fieldName + " - got set with value - " + newValue);
    }

}

have a place-holder for your listeners in the Observable class (in your case MyClass ) and whenever the set method gets called, just fire the event.在 Observable 类(在您的情况下为MyClass )中为您的侦听器提供一个占位符,并且每当调用 set 方法时,只需触发该事件。

public class MyClass {

    List<FieldListener> listeners = new ArrayList<FieldListener>(); // the placeholder for listeners

    private String field1;
    private String field2;

    /**
     * @param field1 the field1 to set
     */
    public void setField1(String field1) {
        fireEvent("field1", field1);
        this.field1 = field1;
    }
    /**
     * @param field2 the field2 to set
     */
    public void setField2(String field2) {
        fireEvent("field2", field2);
        this.field2 = field2;
    }

    public void addListener(FieldListener l) {
        if(l != null) listeners.add(l);
    }

    public void fireEvent(String fieldName, Object newValue) {
        for(FieldListener l : listeners) {
            l.fieldValueChanged(fieldName, newValue);
        }
    }

    public static void main(String [] args) {
        MyClass m = new MyClass();
        m.addListener(new SampleObserver());
        m.setField1("s");
        m.setField2("v");
    }

}

I think what you are searching the a java.bean.PropertyChangeListener which is the Observer-Pattern in Java.我认为您正在搜索java.bean.PropertyChangeListener ,它是 Java 中的观察者模式。

Basically you add code to all setters to call the method in the PropertyChangeListener to inform all observers that the value is changed.基本上,您将代码添加到所有 setter 以调用PropertyChangeListener中的方法,以通知所有观察者该值已更改。

This is the normal Java way.这是正常的Java方式。

Sounds like you want the Observer / Observable pattern.听起来你想要Observer / Observable模式。 Basically a state listener registers (observes) with the myClass object to receive a notification when something changes.基本上,状态侦听器向myClass对象注册(观察),以便在发生变化时接收通知。

That's hard to say, because we don't know why you need to monitor the fields and what neds to be done with the changes.这很难说,因为我们不知道您为什么需要监视这些字段以及要对这些更改执行什么操作。

One thing you could do is to add listeners to your object (Observer pattern), so that classes, interested in the changes, can get notified about it.您可以做的一件事是将侦听器添加到您的对象(观察者模式),以便对更改感兴趣的类可以收到有关它的通知。 This of course works only if you have access to the interested classes and can modify them accordingly.这当然只有在您可以访问感兴趣的类并且可以相应地修改它们时才有效。

If you have no access and anybody can call your methods, you might have to go via reflection.如果您无权访问并且任何人都可以调用您的方法,那么您可能必须通过反射进行。 If you need a better answer, you must give more details.如果您需要更好的答案,您必须提供更多详细信息。

Update更新

Since you only want to keep track of it internaly via setters, then you can simply put in your setter, whatever you need to keep track of the changes.由于您只想通过设置器在内部跟踪它,因此您可以简单地放入您的设置器,无论您需要什么来跟踪更改。 One solution could be to create a separate class, which stores the changes.一种解决方案可能是创建一个单独的类来存储更改。 So whenever you do some update, you call the tracker class and tell it the information you want to keep track of, like old value, new value, timestamp, whatever.因此,每当您进行一些更新时,您都会调用跟踪器类并告诉它您想要跟踪的信息,例如旧值、新值、时间戳等。

I realize I am late to the party and that the other answers here are valid, but I wanted to offer an alternative that might be simpler for anyone else that comes looking.我意识到我迟到了,这里的其他答案是有效的,但我想提供一个替代方案,对于其他任何人来说可能更简单。

My suggestion is to use Optional for your fields but not for your getters/setters.我的建议是将Optional用于您的字段,但不用于您的 getter/setter。 In this way anything that is not Optional.empty() has been changed/updated.通过这种方式,任何不是Optional.empty()的东西都已更改/更新。

import java.util.Optional;

public class MyClass
{
    private Optional<String> field1 = Optional.empty();
    private Optional<String> field2 = Optional.empty();
    private Optional<String> field3 = Optional.empty();

    public String getField1()
    {
        return field1.orElse(null);
    }

    public void setField1(String value)
    {
        field1 = Optional.ofNullable(value);
    }

    public String getField2()
    {
        return field2.orElse(null);
    }

    public void setField2(String value)
    {
        field2 = Optional.ofNullable(value);
    }

    public String getField3()
    {
        return field3.orElse(null);
    }

    public void setField3(String value)
    {
        field3 = Optional.ofNullable(value);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM