(Big talk design pattern kotlin version) 14. Observer pattern

(Big talk design pattern kotlin version) 14. Observer pattern

Observer mode

definition

The observer Observermodel is also called the publish-subscribe Publish/Subscribemodel. It defines a one-to-many dependency relationship, allowing multiple observer objects to monitor a certain subject Subjectobject at the same time . When this subject object changes in state, it will notify all observer objects so that they can update themselves automatically.

UML diagram

Implementation code

SubjectAn abstract theme class that supports adding, removing, and notifying observer objects.

/**
 * @create on 2020/6/27 23:12
 * @description    
 * @author mrdonkey
 */
abstract class Subject {
    private val observers = arrayListOf<Observer>()

    fun attach(observer: Observer) {
        observers.add(observer)
    }

    fun detach(observer: Observer) {
        observers.remove(observer)
    }

    fun notifyObserver() {
        observers.forEach {
            it.update()
        }
    }
}
 

ObserverAn abstract observer, a updatemethod that is called when the state of the subject changes.

/**
 * @create on 2020/6/27 23:14
 * @description  
 * @author mrdonkey
 */
abstract class Observer {
    abstract fun update()
}
 

ConcreteSubject The specific subject implementation class provides all the functions of the subject and increases the state of the subject.

/**
 * @create on 2020/6/27 23:15
 * @description  
 * @author mrdonkey
 */
class ConcreteSubject : Subject() {
    var subjectState = ""
}
 

ConcreteObserverThe specific observer defines the updatespecific implementation when the subject notification is received .

/**
 * @create on 2020/6/27 23:15
 * @description  
 * @author mrdonkey
 */
class ConcreteObserver(var sub: ConcreteSubject, var name: String) : Observer() {
    private var observerState = ""

    override fun update() {
        observerState = sub.subjectState
        println("$name--->update:$observerState")
    }
    
}
 

Client Client test class

/**
 * @create on 2020/6/27 23:23
 * @description  
 * @author mrdonkey
 */
class Client {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val concreteSubject = ConcreteSubject()
            concreteSubject.attach(ConcreteObserver(concreteSubject, "A"))
            concreteSubject.attach(ConcreteObserver(concreteSubject, "B"))
            concreteSubject.subjectState="HaHa"
            concreteSubject.notifyObserver()
        }
    }
}
 

Test Results:

A--->update:HaHa
B--->update:HaHa
 

analysis

  • Meaning (depending on a realization of the principle of inversion)
  • scenes to be used
  • The insufficiency is the dependency inversion principle, which makes it necessary to rely on . Without this interface, the notifier in the above example cannot notify the observer. Furthermore, only this type of observer can be specified, and it is not easy to expand the observer to support other interfaces;
  • Expand practical some cases , moreover , in order to meet this effect, we need to achieve.

Event delegation mechanism

definition

First there is the observer mode, and then there is the delegated event mechanism. A delegate is a type of reference method. Once a method is assigned to the delegate, the delegate will have exactly the same behavior as the method. Class`, the delegated instance will represent a specific function.

Modify the code to implement a simple delegation

Under the premise of the observer mode in the above example, we remove it and let maintain a function list, which is loaded with the corresponding operation function for each observer (corresponding to the updatemethod defined by the abstract observer , but each observer is not necessarily The update method) Simply put, it is to change from saving to saving , turning the defined fixed abstract interface into a function type, so as to achieve the effect of supporting different types of observers and further decouple the program.

SubjectSubject interface, providing notifyObservermethods to notify observers

/**
 * @create on 2020/6/27 23:28
 * @description  
 * @author mrdonkey
 */
interface Subject {
    fun notifyObserver()
}
 

ConcreteSubjectFor specific topics, eventHandlersave an observer's key (for easy deletion) and the update method corresponding to the observer. In this example, a method with no parameters and no return value is defined() -> Unit

/**
 * @create on 2020/6/27 23:29
 * @description  
 * @author mrdonkey
 */
class ConcreteSubject : Subject {

    private var eventHandler: HashMap<Int, () -> Unit> = hashMapOf()//

    override fun notifyObserver() {
        eventHandler.forEach { event ->
            event.value()//
        }
    }

    fun attach(key: Int, event: () -> Unit) {
        eventHandler[key] = event
    }

    fun detach(key: Int) {
        eventHandler.remove(key)

    }

}
 

ConcreteObserverA/ConcreteObserverB Specific observers A and B

class ConcreteObserverA {

    fun updateObserverA(){
        println("A--->updateObserverA")
    }
}

class ConcreteObserverB {

    fun updateObserverB(){
        println("B--->updateObserverB")
    }
}
 

Client Client test

class Client {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val concreteSubject = ConcreteSubject()
            concreteSubject.attach(1) { ConcreteObserverA().updateObserverA() }
            concreteSubject.attach(2) { ConcreteObserverB().updateObserverB() }
            concreteSubject.detach(2)
            concreteSubject.notifyObserver()
        }
    }
}
 

Output result:

A--->updateObserverA
 

analysis

  • Advantage , all methods will be awakened in sequence during execution.
  • insufficient