Patrones de diseño: patrón de observador (observador) y modelo de evento delegado (DEM)

1. Introducción

El modo de observador, también conocido como modo de publicación-suscripción, es una relación de uno a muchos. Cuando se produce un determinado cambio en lo observado, se realizan los cambios correspondientes en sus observadores. Por ejemplo, hay 2 estudiantes en el laboratorio de posgrado de una escuela, 2 estudiantes están en el laboratorio una mañana, A está jugando, B está viendo una película, pero tienen miedo de que el jefe entre en la habitación y los arreste. ellos, ¿qué debo hacer? Los dos estudiantes tenían una muy buena relación con los guardias de la oficina de seguridad de la planta baja, les dijeron a los guardias que si veían a su jefe entrar al edificio, inmediatamente les avisarían para que pudieran cambiar a modo de estudio. En este ejemplo, el guardia es la persona a observar (no el jefe), es decir, el editor del evento, y los dos estudiantes son los observadores, siempre y cuando se registren con el guardia y un grupo de guardias envíen mensajes. , pueden recibir notificaciones. hacer cambio.

2 ventajas del patrón observador

Desacoplamiento. El trabajo realizado por el patrón del observador es desacoplar, de modo que tanto el observador como lo observado dependen de la abstracción de sus respectivas capas superiores, en lugar de la implementación específica, de modo que el código de implementación específico cambia del observador y lo observado cambiará. no afectarse unos a otros. .

3 escenarios aplicables

Cuando un cambio en un objeto necesita causar un cambio en otros objetos, es un cambio de estado, no un cambio de código. Especialmente cuando un objeto cambia sin saber cuántos otros objetos cambiarán.

4 Ejemplo de código de observador

4.1 Observables abstractos

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 10:47
 * @description: 通知者的接口
 **/

public interface Subject {

    /**
     * 添加观察者
     *
     * @param observer 观察者
     */
    void addObserver(Observer observer);

    /**
     * 删除观察者
     *
     * @param observer 观察者
     */
    void deleteObserver(Observer observer);

    /**
     * 通知观察者
     *
     * @param msg 通知信息
     */
    void notifyAll(String msg);
}

4.2 Observadores concretos

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 11:02
 **/

public class ConcreteSubject implements Subject{

    //确保观察者不会重复存在
    Set<Observer> observers = new HashSet<>();

    @Override
    public void addObserver(Observer observer) {
        if (observer == null){
            throw new NullPointerException("观察者不允许为空");
        }
        observers.add(observer);
    }

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

    @Override
    public void notifyAll(String msg) {
        for (Observer o: observers) {
            o.update(this, msg);
        }
    }
}

4.3 Observadores abstractos

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 10:47
 * @description: 观察者的接口
 **/

public interface Observer {


    /**
     * 接收到通知,更新自我的状态
     *
     * @param subject 通知者
     * @param msg 通知信息
     */
    void update(Subject subject, String msg);
}

4.4 Concrete Observer 1 - Cómo jugar el juego

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 11:09
 **/

public class GameObserver implements Observer{
    @Override
    public void update(Subject subject, String msg) {
        System.out.println("这里是" + subject.getClass() + "," + msg + "请停止打游戏");
    }
}

4.5 Concrete Observer 2 - Ver películas

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 11:09
 **/

public class MovieObserver implements Observer{
    @Override
    public void update(Subject subject, String msg) {
        System.out.println("这里是" + subject.getClass() + "," + msg + "请停止看电影");
    }
}

4.6 Programa principal

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 11:18
 **/
public class MainClass {
    public static void main(String[] args) throws Exception {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        GameObserver gameObserver = new GameObserver();
        MovieObserver movieObserver = new MovieObserver();

        concreteSubject.addObserver(gameObserver);
        concreteSubject.addObserver(movieObserver);

        concreteSubject.notifyAll("有内鬼");
    }
}

4.7 Resultados de la ejecución

5 desventajas del patrón observador

1. Aunque tanto el observador como lo observado están abstraídos, las interfaces aún están acopladas entre sí, por ejemplo, cuando definimos la interfaz del Sujeto, agregar y eliminar el observador todavía está acoplado con la interfaz del Observador.

2. El método lanzado por el observador es fijo. Los estudiantes que juegan el juego reciben la notificación y quieren cerrar el juego, y luego salen corriendo antes de que llegue el maestro. Los estudiantes que ven la película quieren cerrar la película antes que el maestro. viene Abra la idea para obtener una buena impresión, pero no es posible ahora, y el observador llama al método de actualización de manera uniforme.

6 Modelo de evento delegado (DEM)

Entendimiento personal, encomienda es transferir las cosas que necesitas hacer antes a otros para que las hagan. El rol de sujeto es responsable de publicar eventos, y el observador se suscribe a un tema específico para los eventos que le interesan. Cuando un tema específico genera un evento, notificará a todos los suscriptores interesados. Y puede suscribirse y cancelar dinámicamente. En DEM, los editores se denominan fuentes de eventos y los suscriptores se denominan detectores de eventos.

¿Cómo se logra? Primero definimos un evento Evento. La tarea de Evento es ejecutar el método del objeto entrante. De esta manera, diferentes objetos pueden tener diferentes métodos, lo que resuelve el segundo problema de las deficiencias: el método fijo del observador. Defina otra clase EventHandler, que es responsable de agregar eventos y publicar eventos, y el Sujeto solo necesita pasar la clase EventHandler, agregar eventos suscritos y publicar mensajes, lo que resuelve el primer problema sobre el acoplamiento.

7 Implementación de código de evento de delegado

7.1 Clase de evento

**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 14:14
 **/
@Data
@Setter
@Getter
public class Event {

    /**
     * 委托事件者
     */
    private Object object;

    /**
     * 委托执行的方法
     */
    private String methodName;

    /**
     * 委托执行的方法参数
     */
    private Object[] params;

    /**
     * 执行方法的参数类型
     */
    private Class[] paramTypes;

    public Event(){
        //无参构造
    }
    public Event(Object object, String methodName, Object...params){
        this.object = object;
        this.methodName = methodName;
        this.params = params;
        contractParamTypes(this.params);
    }

    /**
     *构造参数类型数组
     *
     */
    private void contractParamTypes(Object[] params){
        this.paramTypes = new Class[params.length];
        for (int i = 0; i < params.length; i++) {
            this.paramTypes[i] = params[i].getClass();
        }
    }

    /**
     *执行委托的方法
     *
     */
    public void invoke() throws Exception {
        Method method = object.getClass().getMethod(this.methodName, this.paramTypes);
        method.invoke(this.object, this.params);
    }

}

7.2 Clase EventHandler


/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 14:37
 **/
@Data
public class EventHandler {

    private Set<Event> events;

    public EventHandler(){
        this.events = new HashSet<>();
    }

     //相当于添加一个事件,关联一个观察者

    public void addEvent(Object object, String methodName, java.lang.Object[] args){
        events.add(new Event(object, methodName, args));
    }

    //发布事件
    public void subscribeNotice() throws Exception {
        for (Event e: events){
            e.invoke();
        }
    }
}

7.3 Interfaz abstracta de Source Observer

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 14:56
 **/
public interface Source {

    /**
     * 添加观察者
     *
     * @param object 观察者实例
     * @param methodName 执行方法名称
     * @param args 方法的参数
     */
    void addListener(Object object, String methodName, Object...args);

    /**
     * 通知
     * @throws Exception
     */
    void subscribeNotice() throws Exception;
}

7.4 Clase de implementación concreta fuente ConcreteSource

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 14:59
 **/
public class ConcreteSource implements Source{

    private final EventHandler eventHandler = new EventHandler();

    @Override
    public void addListener(Object object, String methodName, Object...args) {
        eventHandler.addEvent(object, methodName, args);
    }

    @Override
    public void subscribeNotice() throws Exception {
        eventHandler.subscribeNotice();
    }
}

7.5 Observador 1 - Observador de TV TvObserver

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 15:18
 **/
public class TvObserver {

    public void stopWatchTv(String reason){
        System.out.println("赶快别看电视了, " + reason);
    }
}

7.6 Observador 2 - Adjuntar FishObserver

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 15:18
 **/
public class AttachFishObserver {

    public void stopAttachFish(Date date) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(f.format(date));
        System.out.println("赶快别看摸鱼了, 看看时间啊,我的哥");
    }
}

7.7 Función principal

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-08-31 11:18
 **/
public class MainClass {
    public static void main(String[] args) throws Exception {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        GameObserver gameObserver = new GameObserver();
        MovieObserver movieObserver = new MovieObserver();

        concreteSubject.addObserver(gameObserver);
        concreteSubject.addObserver(movieObserver);

        concreteSubject.notifyAll("有内鬼");

        System.out.println("---------------------分界线----------------------");

        ConcreteSource concreteSource = new ConcreteSource();

        TvObserver tvObserver = new TvObserver();
        AttachFishObserver attachFishObserver = new AttachFishObserver();

        concreteSource.addListener(tvObserver, "stopWatchTv", "你老妈回来了");
        concreteSource.addListener(attachFishObserver, "stopAttachFish", new Date());

        concreteSource.subscribeNotice();
    }
}

7.8 Resultados de la ejecución

8 Resumen

Según mi propio entendimiento, este artículo presenta el patrón de observador y, a través de las deficiencias del patrón de observador, conduce al evento delegado y proporciona el código y el resultado de la ejecución.

9 citas

1. Implementar el patrón de delegación de eventos en lenguaje java

2. Patrón de observadores y delegación de eventos

3. Patrón de diseño del observador frente a delegación de eventos (java)

4. "Patrones de diseño Dahua"

10 código fuente

https://github.com/airhonor/design-pattern-learning

Supongo que te gusta

Origin blog.csdn.net/honor_zhang/article/details/120020490
Recomendado
Clasificación