Patrón de observador "Patrones de diseño"

Patrón de observador "Patrones de diseño"

Definición :

  • El modo de observador, también conocido como modo de publicación-suscripción , define una relación de dependencia de uno a muchos, y un objeto sujeto puede ser observado (supervisado) por varios objetos de observador al mismo tiempo. Cuando cambia el estado del objeto sujeto, todos los objetos observadores pueden ser notificados y actualizados automáticamente .
  • El núcleo del modo observador es desacoplar el observador del observado y asociar los dos de una manera similar a la publicación-suscripción, de modo que la actualización del estado del observado pueda notificarse a los observadores que estén interesados ​​en ella.

Los roles compositivos del patrón observador :

  • Sujeto (Subject) : también conocido como notificador abstracto, generalmente implementado por una interfaz o clase abstracta. Contiene una colección de referencias a todos los objetos de observador, define métodos para agregar y eliminar cualquier objeto de observador y métodos para notificar a todos los objetos de observador.
  • ConcreteSubject : también conocido como notificador específico, cuando el estado (datos) cambia, envía una notificación a todos los observadores.
  • Observador abstracto (Observer) : generalmente implementado por una clase abstracta o una interfaz, define una interfaz para todos los observadores específicos, se actualiza cuando el sujeto lo notifica y, por lo general, contiene update()métodos
  • Observador concreto (ConcreteObserver) : implemente la interfaz de actualización del observador abstracto y, al mismo tiempo, mantenga una referencia al objeto sujeto específico en el observador concreto, almacene el estado relevante del observador específico, y estos estados deben ser consistentes con el estado del objeto sujeto específico.

Diagrama de clases UML del patrón observador :

inserte la descripción de la imagen aquí

Tome un caso de escenario de aplicación muy simple: simule una cuenta oficial de noticias, los usuarios pueden suscribirse y cancelar la suscripción de la cuenta oficial a voluntad, y cuando la cuenta oficial de noticias tenga comunicados de prensa, se notificará a todos los usuarios que se hayan suscrito a la cuenta oficial. En cualquier momento, todos los suscriptores reciben las mismas actualizaciones de noticias.

Asunto abstracto Asunto :

public interface Subject {
    
    
    /**
     * 增加观察者对象
     * @param observer
     */
    void attach(Observer observer);

    /**
     * 删除观察者对象
     * @param observer
     */
    void detach(Observer observer);
    /**
     * 通知所有观察者对象
     */
    void notifyObserver();
}

Materia específica ConcreteSubject :

public class ConcreteSubject implements Subject{
    
    
    private List<Observer> observers = new ArrayList<>();
    private String subjectState;

    public String getSubjectState() {
    
    
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
    
    
        this.subjectState = subjectState;
    }

    @Override
    public void attach(Observer observer) {
    
    
        observers.add(observer);
    }

    @Override
    public void detach(Observer observer) {
    
    
        observers.remove(observer);
    }

    @Override
    public void notifyObserver() {
    
    
        for (Observer observer : observers) {
    
    
            observer.update();
        }
    }
}

Observador abstracto Observador :

public interface Observer {
    
    
    /**
     * 更新观察者的状态
     */
    void update();
}

Observador concreto ConcreteObserver :

public class ConcreteObserver implements Observer{
    
    
    private String name;
    private String observerState;
    private ConcreteSubject subject;

    public ConcreteObserver(String name, ConcreteSubject subject) {
    
    
        this.name = name;
        this.subject = subject;
    }

    @Override
    public void update() {
    
    
        observerState = subject.getSubjectState();
        System.out.println(String.format("观察者%s收到的消息是:%s", name, observerState));
    }
}

Cliente Cliente :

public class Client {
    
    
    public static void main(String[] args) {
    
    
        ConcreteSubject concreteSubject = new ConcreteSubject();
        concreteSubject.attach(new ConcreteObserver("node1", concreteSubject));
        concreteSubject.attach(new ConcreteObserver("node2", concreteSubject));
        concreteSubject.attach(new ConcreteObserver("node3", concreteSubject));
        concreteSubject.setSubjectState("Hello, observers!");
        concreteSubject.notifyObserver();
    }
}

Resultado de salida :

观察者node1收到的消息是:Hello, observers!
观察者node2收到的消息是:Hello, observers!
观察者node3收到的消息是:Hello, observers!

De hecho, el código fuente de JDK proporciona un esqueleto para usar rápidamente el modo observador java.util, Observerla interfaz (equivalente a un notificador abstracto) y Observablela clase (equivalente a un objeto observador) bajo el paquete.

Observer 接口

/**
*  抽象通知者
*/
public interface Observer {
    
    
    void update(Observable o, Object arg);
}

Observer 类

public class Observable {
    
    
    private boolean changed = false;
    private Vector<Observer> obs;
    public Observable() {
    
    
        obs = new Vector<>();
    }
    public synchronized void addObserver(Observer o) {
    
    
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
    
    
            obs.addElement(o);
        }
    }

    public synchronized void deleteObserver(Observer o) {
    
    
        obs.removeElement(o);
    }
 
    public void notifyObservers() {
    
    
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
    
    
        Object[] arrLocal;

        synchronized (this) {
    
    
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    
    public synchronized void deleteObservers() {
    
    
        obs.removeAllElements();
    }
    
    protected synchronized void setChanged() {
    
    
        changed = true;
    }
   
    protected synchronized void clearChanged() {
    
    
        changed = false;
    }
   
    public synchronized boolean hasChanged() {
    
    
        return changed;
    }
    
    public synchronized int countObservers() {
    
    
        return obs.size();
    }
}

La interfaz de Observer y el diagrama de clase UML de la clase Observable se muestran a continuación :

inserte la descripción de la imagen aquí

Ventajas del patrón de observador :

  • Establecer un acoplamiento abstracto entre el objetivo de observación y el observador El objetivo de observación solo necesita mantener una colección de observadores abstractos sin conocer sus observadores específicos, de modo que cada cambio no afecte el cambio del otro lado, que está en línea con la dependencia. inversión en principio.
  • Se admite la comunicación de difusión . Los objetivos de observación enviarán notificaciones a todos los objetos de observación registrados, simplificando la dificultad del diseño del sistema de uno a muchos.
  • Satisface los requisitos del principio abierto-cerrado, agregando nuevos observadores específicos no necesita modificar el código del sistema original . También es conveniente agregar un nuevo objetivo de observación cuando no existe una correlación entre el observador específico y el objetivo de observación.

Desventajas del patrón de observador :

  • Si un objeto objetivo de observación tiene muchos observadores directos e indirectos, llevará mucho tiempo notificar a todos los observadores.
  • Si existe una dependencia circular entre el observador y el objetivo observado, el objetivo observado activará una llamada cíclica entre ellos, lo que posiblemente bloquee el sistema.
  • No existe un mecanismo correspondiente para que el observador sepa cómo ha cambiado el objeto objetivo observado, sino solo para saber que el objetivo observado ha cambiado.

Escenarios de aplicación del modo observador :

  • Un modelo abstracto tiene dos aspectos, uno de los cuales depende del otro. En este momento, el patrón del observador se puede usar para encapsular los dos en objetos independientes para que se puedan cambiar y reutilizar de forma independiente.
  • Un cambio en un objeto hará que uno o más objetos cambien, y no se sabe exactamente cuántos objetos cambiarán o quiénes son esos objetos.
  • Necesita crear una cadena de activación en el sistema, el comportamiento del objeto A afectará al objeto B, el comportamiento del objeto B afectará al objeto C... Puede utilizar el patrón de observador para crear un mecanismo de activación de cadena.

Supongo que te gusta

Origin blog.csdn.net/weixin_43252521/article/details/129929855
Recomendado
Clasificación