2016-06-24 2 views
2

Скажите, что у меня есть набор элементов, например List<Item>, и мне нужно проверить, не изменен ли какой-либо элемент из класса-обертки, например, значение любого свойства элемента изменяется через сеттер:Как обнаружить изменения в объекте?

List<Item> items = itemsWrapper.getItems(); // itemsWrapper contains a list of items 
Item anItem = items.get(index); 
item.setProperty(property); 
itemsWrapper.hasChanged(); // ?????? 

Я пытаюсь выяснить способ достижения последнего утверждения или что-то подобное.

Я вижу, что есть похожие вопросы, например this one, где используется Hibernate, но ответ очень расплывчатый, и мой вопрос не связан с DB. В нем также упоминается создание списка слушателей, но я не уверен, что его можно было бы сделать.

Или this other question, где выбранный ответ предполагает использование флага dirty, который необходимо увеличить каждый раз при изменении свойства. Тем не менее, мой класс фактически получил бы грязнее, как ни парадоксально, и мне нужно будет изменить десятки методов, которые изменяют свойства объекта.

Есть ли другой подход, лучше, если он прозрачен?

+2

«Наблюдатель» Выкройка: itemsWrapper наблюдает за предметами для изменения. – Fildor

+0

Можете ли вы дать нам больше информации? Я подозреваю, что вы можете захотеть отслеживать где-то еще изменения, а не сама коллекция. –

+0

@Fildor Я также проверил подход шаблона наблюдателя, но я не вижу, как это отличается от подхода «грязного» флага, поскольку на самом деле «делает мой код более грязным», потому что мне все равно придется обновлять все мои сеттеры (и методы модификации объекта). – dabadaba

ответ

0

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

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

+0

@TimBiegeleisen Исправлено –

0

Лучшим способом было бы использовать java.util.Observable Класс, который имеет функцию boolean hasChanged(), как говорит ваш прецедент. Это отсылка ответ: When should we use Observer and Observable

Просто пример:

<code>import java.util.Observable; 
import java.util.Observer; 
// First observer 
class FirstNewsReader implements Observer { 
    public void update(Observable obj, Object arg) { 
     System.out.println("FirstNewsReader got The news:"+(String)arg); 
    } 
} 
//Second Observer 
class SecondNewsReader implements Observer { 
    public void update(Observable obj, Object arg) { 
     System.out.println("SecondNewsReader got The news:"+(String)arg); 
    } 
} 
// This is the class being observed. 
class News extends Observable { 
    void news() { 
     String[] news = {"News 1", "News 2", "News 3"}; 
     for(String s: news){ 
      //set change 
      setChanged(); 
      //notify observers for change 
      notifyObservers(s); 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       System.out.println("Error Occurred."); 
      } 
     } 
    } 
} 
//Run Observer and Observable 
class ObserverObservableDemo { 
    public static void main(String args[]) { 
     News observedNews = new News(); 
     FirstNewsReader reader1 = new FirstNewsReader(); 
     SecondNewsReader reader2 = new SecondNewsReader(); 
     observedNews.addObserver(reader1); 
     observedNews.addObserver(reader2); 
     observedNews.news();   
    } 
}</code> 
+0

Не могли бы вы дать краткий макет итогового макета классов? Я не могу понять, как мне его настроить. – dabadaba

+0

@dabadaba: взгляните на мой отредактированный ответ –

0

Используйте паттерн наблюдатель вашего класса Item/обертку. JavaFX (включая свойства java 7.something) уже поддерживают поддержку таких функций.

Пример:

class Item { 

    private final ObjectProperty<Object> property = new SimpleObjectProperty<Object>(); 

    public final Object getProperty() { 
     return this.property.get(); 
    } 

    public final void setProperty(Object value) { 
     this.property.set(value); 
    } 

    public final ObjectProperty<Object> propertyProperty() { 
     return this.property; 
    } 
} 
class Listener implements InvalidationListener { 

    private boolean changed = false; 

    @Override 
    public void invalidated(Observable observable) { 
     changed = true; 
    } 

    public boolean isChanged() { 
     return changed; 
    } 

    public void resetChanged() { 
     this.changed = false; 
    } 

} 
// trigger update changes when the property changes 
ObservableList<Item> list = FXCollections.observableArrayList(e -> new Observable[]{e.propertyProperty()}); 

list.addAll(new Item(), new Item()); 

Listener listener = new Listener(); 
list.addListener(listener); 
System.out.println(listener.isChanged()); 

list.get(0).setProperty(""); 
System.out.println(listener.isChanged()); 
listener.resetChanged(); 

list.get(1).setProperty(1); 
System.out.println(listener.isChanged()); 

listener.resetChanged(); 

list.add(new Item()); 
System.out.println(listener.isChanged()); 
0

Самым прозрачным способом является использование Spring AOP AspectJ. Создайте свой класс Aspect и используйте @Before или @ после аннотаций для вашего метода item.setProperty().

+0

Не могли бы вы дать более подробную информацию? – dabadaba

+0

Вот простой пример, который регистрируется при вызове метода http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/ –

Смежные вопросы