<commit_before>//////////////////////////////////////////

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.

//////////////////////////////////////////

= Observer Pattern


The https://en.wikipedia.org/wiki/Observer_pattern[Observer Pattern] allows one or more _observers_ to be notified
about changes or events from a _subject_ object.

[plantuml, ChainOfResponsibilityClasses, png]
....
skinparam ClassBorderColor<<Hidden>> Transparent
skinparam ClassBackgroundColor<<Hidden>> Transparent
skinparam ClassStereotypeFontColor<<Hidden>> Transparent
skinparam ClassFontSize<<Hidden>> 24
skinparam ClassFontStyle<<Hidden>> bold
skinparam shadowing<<Hidden>> false
hide <<Hidden>> circle
class "..." as ConcreteHidden
class ConcreteHidden <<Hidden>> {
}
class Observer {
    +update()
}
class ConcreteObserver1 {
    +update()
}
class ConcreteObserverN {
    +update()
}
hide Observer fields
class Subject {
    -observerCollection
    +registerObserver(observer)
    +unregisterObserver(observer)
    +notifyObservers()
}
Observer <|-- ConcreteObserver1
Observer <|-[hidden]- ConcreteHidden
Observer <|-- ConcreteObserverN
Observer ---r---o Subject
ConcreteObserver1 .r[hidden]. ConcreteHidden
....

== Example

Here is a typical implementation of the classic pattern:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_classic,indent=0]
----

Using Closures, we can avoid creating the concrete observer classes as shown below:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_closures,indent=0]
----

As a variation for Groovy 3+, let's consider dropping the `Observer` interface and using lambdas as shown below:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_lambdas,indent=0]
----

We are now calling the `accept` method from `Consumer` rather
than the `update` method from `Observer`.

== @Bindable and @Vetoable

The JDK has some built-in classes which follow the observer pattern.
The `java.util.Observer` and `java.util.Observable` classes are deprecated from JDK 9 due to various limitations.
Instead, you are recommended to use various more powerful classes in the `java.beans` package such as `java.beans.PropertyChangeListener`.
Luckily, Groovy has some built-in transforms (gapi:groovy.beans.Bindable[] and gapi:groovy.beans.Vetoable[])
which support for some key classes from that package.

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_bindable,indent=0]
----

Here, methods like `addPropertyChangeListener` perform the same role as `registerObserver` in previous examples.
There is a `firePropertyChange` method corresponding to `notifyAll`/`notifyObservers` in previous examples but Groovy adds that
automatically here, so it isn't visible in the source code. There is also a `propertyChange` method that corresponds
to the `update` method in previous examples, though again, that isn't visible here.
<commit_msg>fix image name<commit_after>//////////////////////////////////////////

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.

//////////////////////////////////////////

= Observer Pattern


The https://en.wikipedia.org/wiki/Observer_pattern[Observer Pattern] allows one or more _observers_ to be notified
about changes or events from a _subject_ object.

[plantuml, ObserverClasses, png]
....
skinparam ClassBorderColor<<Hidden>> Transparent
skinparam ClassBackgroundColor<<Hidden>> Transparent
skinparam ClassStereotypeFontColor<<Hidden>> Transparent
skinparam ClassFontSize<<Hidden>> 24
skinparam ClassFontStyle<<Hidden>> bold
skinparam shadowing<<Hidden>> false
hide <<Hidden>> circle
class "..." as ConcreteHidden
class ConcreteHidden <<Hidden>> {
}
class Observer {
    +update()
}
class ConcreteObserver1 {
    +update()
}
class ConcreteObserverN {
    +update()
}
hide Observer fields
class Subject {
    -observerCollection
    +registerObserver(observer)
    +unregisterObserver(observer)
    +notifyObservers()
}
Observer <|-- ConcreteObserver1
Observer <|-[hidden]- ConcreteHidden
Observer <|-- ConcreteObserverN
Observer ---r---o Subject
ConcreteObserver1 .r[hidden]. ConcreteHidden
....

== Example

Here is a typical implementation of the classic pattern:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_classic,indent=0]
----

Using Closures, we can avoid creating the concrete observer classes as shown below:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_closures,indent=0]
----

As a variation for Groovy 3+, let's consider dropping the `Observer` interface and using lambdas as shown below:

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_lambdas,indent=0]
----

We are now calling the `accept` method from `Consumer` rather
than the `update` method from `Observer`.

== @Bindable and @Vetoable

The JDK has some built-in classes which follow the observer pattern.
The `java.util.Observer` and `java.util.Observable` classes are deprecated from JDK 9 due to various limitations.
Instead, you are recommended to use various more powerful classes in the `java.beans` package such as `java.beans.PropertyChangeListener`.
Luckily, Groovy has some built-in transforms (gapi:groovy.beans.Bindable[] and gapi:groovy.beans.Vetoable[])
which support for some key classes from that package.

[source,groovy]
----
include::../test/DesignPatternsTest.groovy[tags=observer_bindable,indent=0]
----

Here, methods like `addPropertyChangeListener` perform the same role as `registerObserver` in previous examples.
There is a `firePropertyChange` method corresponding to `notifyAll`/`notifyObservers` in previous examples but Groovy adds that
automatically here, so it isn't visible in the source code. There is also a `propertyChange` method that corresponds
to the `update` method in previous examples, though again, that isn't visible here.

{'fraction_non_alphanumeric': 0.10957041870581838, 'fraction_numerical': 0.004078303425774877, 'mean_word_length': 4.273835125448029, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3626131', 'n_tokens_mistral': 1992, 'n_tokens_neox': 1910, 'n_words': 766}