Patrones de diseño_Patrones de comportamiento - "Patrones de observación"

Patrones de diseño_Patrones de comportamiento - "Patrones de observación"

Las notas están organizadas a partir de la explicación detallada de los patrones de diseño de Java por programadores de caballos oscuros, 23 patrones de diseño de Java (diagrama + análisis de código fuente del marco + combate real)

descripción general

definición

  • El modo de observador, también conocido como modo de publicación-suscripción (Publicar/Suscribir), define una relación de dependencia de uno a muchos, lo que permite que varios objetos de observador escuchen un objeto sujeto al mismo tiempo. El objeto sujeto notifica a todos los objetos observadores los cambios de estado, lo que les permite actualizarse automáticamente.

estructura

El patrón de observador tiene los siguientes roles:

  • Sujeto: sujeto abstracto (resumen observado), el rol de sujeto abstracto guarda todos los objetos de observador en una colección, cada sujeto puede tener cualquier número de observadores, el sujeto abstracto proporciona una interfaz, puede agregar y eliminar objetos de observador.
  • ConcreteSubject: Sujeto específico (observador específico), este rol almacena el estado relevante en el objeto observador específico y envía una notificación a todos los observadores registrados cuando cambia el estado interno del sujeto específico.
  • Observador: el observador abstracto es una clase abstracta de observador, que define una interfaz de actualización, de modo que se actualiza cuando se le notifican cambios de tema.
  • ConcrereObserver: Observador concreto, que implementa la interfaz de actualización definida por el observador abstracto, para actualizar su propio estado cuando es notificado de cambios de tema.

Realización de casos

[Ejemplo] Cuenta oficial de WeChat

Al usar la cuenta oficial de WeChat, todos tendrán esa experiencia. Cuando haya una nueva actualización de contenido en la cuenta oficial que sigue, se enviará al cliente de WeChat que sigue la cuenta oficial. Usamos el modo de observador para simular tal escenario. El usuario de WeChat es el observador, y la cuenta oficial de WeChat es el observado (rol de sujeto). Hay varios usuarios de WeChat que siguen la cuenta oficial de Program Ape.

El diagrama de clases es el siguiente:

el código se muestra a continuación:

  • Clase de observador abstracto, que define un método actualizado.

    public interface Observer {
          
          
        void update(String message);
    }
    
  • La clase de observador específica, los usuarios de WeChat son observadores, que implementa el método de actualización

    public class WeixinUser implements Observer {
          
          
        // 微信用户名
        private String name;
    
        public WeixinUser(String name) {
          
          
            this.name = name;
        }
        
        @Override
        public void update(String message) {
          
          
            System.out.println(name + "-" + message);
        }
    }
    
  • Clase de sujeto abstracto (observado), que proporciona tres métodos de adjuntar, separar y notificar

    public interface Subject {
          
          
        // 增加订阅者(观察者对象)
        public void attach(Observer observer);
    
        // 删除订阅者(观察者对象)
        public void detach(Observer observer);
        
        // 通知订阅者更新消息
        public void notify(String message);
    }
    
  • La cuenta pública de WeChat es una clase de tema específica (específicamente el observador), que almacena los usuarios de WeChat que se suscriben a la cuenta pública e implementa los métodos en el tema abstracto.

    public class SubscriptionSubject implements Subject {
          
          
        // 储存订阅公众号的微信用户
        private List<Observer> weixinUserlist = new ArrayList<Observer>();
    
        @Override
        public void attach(Observer observer) {
          
          
            weixinUserlist.add(observer);
        }
    
        @Override
        public void detach(Observer observer) {
          
          
            weixinUserlist.remove(observer);
        }
    
        @Override
        public void notify(String message) {
          
          
            for (Observer observer : weixinUserlist) {
          
          
                observer.update(message);
            }
        }
    }
    
  • programa cliente

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            // 1.创建公众号对象
            SubscriptionSubject mSubscriptionSubject = new SubscriptionSubject();
            // 2.创建微信用户
            WeiXinUser user1 = new WeiXinUser("孙悟空");
            WeiXinUser user2 = new WeiXinUser("猪悟能");
            WeiXinUser user3 = new WeiXinUser("沙悟净");
            // 3.订阅公众号
            mSubscriptionSubject.attach(user1);
            mSubscriptionSubject.attach(user2);
            mSubscriptionSubject.attach(user3);
            // 4.公众号更新发出消息给订阅的微信用户
            mSubscriptionSubject.notify("传智黑马的专栏更新了");
        }
    }
    

    producción

    孙悟空-传智黑马的专栏更新了
    猪悟能-传智黑马的专栏更新了
    沙悟净-传智黑马的专栏更新了
    

Ventajas y desventajas

ventaja

  • La relación de acoplamiento entre el objetivo y el observador se reduce y existe una relación de acoplamiento abstracta entre los dos.
  • La persona observada envía una notificación y todos los observadores registrados recibirán la información [Se puede realizar el mecanismo de transmisión]

defecto

  • Si hay muchos observadores, tomará tiempo para que todos los observadores reciban notificaciones de los observados.
  • Si el observador tiene una dependencia circular, la notificación enviada por el observador hará que el observador llame circularmente, lo que hará que el sistema se bloquee.

Escenas a utilizar

  • Hay una relación de uno a muchos entre los objetos, y los cambios en el estado de un objeto afectarán a otros objetos.
  • Cuando un modelo abstracto tiene dos aspectos, uno de los cuales depende del otro.

Implementación provista en JDK - Observable/Observer

En Java, los patrones de observador se definen mediante java.util.Observable(抽象主题角色类)y java.util.Observer(抽象观察角色接口), siempre que se implementen sus subclases, se pueden escribir instancias de patrones de observador.

clase observable

La clase Observable es una clase de destino abstracta (observada), que tiene una variable de miembro de la colección Vector para almacenar todos los objetos de observador que se notificarán.

private Vector<Observer> obs;
	
// 在无参构造方法中赋值
public Observable() {
    
    
    obs = new Vector<>();
}

Vamos a presentar sus tres métodos más importantes.

  • void addObserver(Observer o)Método: se utiliza para agregar un nuevo objeto observador a la colección.

    public synchronized void addObserver(Observer o) {
          
          
        if (o == null)
            throw new NullPointerException();
        // 如果不存在则添加到集合中
        if (!obs.contains(o)) {
          
          
            obs.addElement(o);
        }
    }
    
  • void notifyObservers(Object arg)Método: llame al método de actualización de todos los objetos observadores de la colección para notificarles los cambios de datos. Por lo general, los observadores que se unieron al conjunto más tarde serán notificados antes.

    public void notifyObservers() {
          
          
        notifyObservers(null);
    }
    			||
                \/
                    
    public void notifyObservers(Object arg) {
          
          
        Object[] arrLocal;
    
        synchronized (this) {
          
          
            // 只有changed为true才可以执行到下面的for循环
            if (!changed)
                return;
            // 集合转数组
            arrLocal = obs.toArray();
            // 这个方法会将changed置为false 因为即将进行通知
            clearChanged();
        }
    	// 倒序遍历数组 所以这就是为什么越晚加入集合的观察者越先得到通知
        for (int i = arrLocal.length-1; i>=0; i--)
            // 逐一通知观察者(调用update方法)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    
  • void setChange()Método: Se utiliza para establecer una bandera interna de tipo booleano, que indica que el objeto de destino ha cambiado. notificar a los observadores () solo notificará a los observadores cuando sea cierto.

    protected synchronized void setChanged() {
          
          
        changed = true;
    }
    

Interfaz de observador

La interfaz Observer es un observador abstracto que monitorea los cambios en el objeto de destino. Cuando el objeto de destino cambia, se notifica al observador y llama al método de actualización para realizar el trabajo correspondiente.

【Ejemplo】La policía atrapó a un ladrón

El patrón de observador también se puede utilizar para que la policía atrape al ladrón. La policía es el observador y el ladrón es el observado. el código se muestra a continuación:

  • El ladrón es un observador, por lo que necesita heredar la clase Observable

    public class Thief extends Observable {
          
          
    
        private String name;
    
        public Thief(String name) {
          
          
            this.name = name;
        }
        
        public void setName(String name) {
          
          
            this.name = name;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        public void steal() {
          
          
            System.out.println("小偷:我偷东西了,有没有人来抓我!!!");
            super.setChanged(); // changed = true,调用通知的方法 才会执行观察者的update方法
            super.notifyObservers();
        }
    }
    
    
  • La policía es un observador, por lo que necesita implementar la interfaz del observador.

    public class Policemen implements Observer {
          
          
    
        private String name;
    
        public Policemen(String name) {
          
          
            this.name = name;
        }
        public void setName(String name) {
          
          
            this.name = name;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        @Override
        public void update(Observable o, Object arg) {
          
          
            System.out.println(this.getName() + "警察:" + ((Thief) o).getName() + ",我已经盯你很久了,你可以保持沉默,但你所说的将成为呈堂证供!!!");
        }
    }
    
  • codigo del cliente

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            // 创建小偷对象
            Thief t = new Thief("隔壁老王");
            // 创建警察对象
            Policemen p = new Policemen("小李");
            // 让警察盯着小偷(订阅)
            t.addObserver(p);
            // 小偷偷东西(发布)
            t.steal();
        }
    }
    

    producción

    小偷:我偷东西了,有没有人来抓我!!!
    小李警察:隔壁老王,我已经盯你很久了,你可以保持沉默,但你所说的将成为呈堂证供!!!
    

Supongo que te gusta

Origin blog.csdn.net/weixin_53407527/article/details/128628077
Recomendado
Clasificación