Posts /

观察者设计模式

01 Aug 2020

观察者设计模式


观察者模式

定义:

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。该设计模式最重要的作用就是 解耦!将观察者与被观察者解耦,使得他们之间的依赖性更小。

结构:

下图的结构是一个为上位机接收下位机状态的设计的一个类图。

ObserverRole是观察者抽象类。

AlarmLight和DetectIsStop是具体的观察者(订阅者)。

FaultStatusManager是一个具体的被观察者(发布者)。

当被观察者执行addNewStatusChange(msg)之后,被观察者将会调用notifyRoles(),通知所有List当中的对象的时候(通过执行对象中的update方法)。

1595945154834

package javatest.pattern;

import java.util.ArrayList;
import java.util.List;

/**
 * @description: 本类对观察者设计模式进行实现和测试
 * @modifyContent:
 * @author: Maple Chan
 * @date: 2020-07-28 22:08:06
 * @version: 0.0.1
 */
public class ObservationPattern {
    public static void main(String[] args) {
        FaultStatusPublisher faultStatusPublisher = new FaultStatusPublisher();

        System.out.println("Role1 subscribe an publisher!");
        BaseObserverRole role1 = new AlarmLightRole();
        role1.subscribe(faultStatusPublisher);

        System.out.println("Role2 subscribe an publisher!");
        BaseObserverRole role2 = new DetectIsStopRole();
        role2.subscribe(faultStatusPublisher);
        System.out.println("\n\n\n");


        System.out.println("faultStatusPublisher notify a massage!");
        faultStatusPublisher.addNewStatus("alarm: new Message of :" + AlarmLightRole.class);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n\n\n");
        System.out.println("faultStatusPublisher notify another massage!");
        faultStatusPublisher.addNewStatus("detect: new Message of :" + DetectIsStopRole.class);

    }
}
/*
发布者、被观察者基类
*/
abstract class BasePublisher {
    protected List<BaseObserverRole> observerRoles = new ArrayList<>();

    /**
     * 注册观察者
     * @param role
     */
    abstract public void attach(BaseObserverRole role);

    /**
     * 调用BaseObserverRoles的update,通知消息。可以考虑从队列中获取消息,实现消息同步接收发送
     * @param msg
     */
    abstract protected void notifyRoles(String msg);

    /**
     * 添加消息,调用notifyRoles方法。可以考虑队列的方式,完成消息的同步
     * @param msg
     */
    abstract public void addNewStatus(String msg);
}
/*
具体的发布者、被观察者
*/
class FaultStatusPublisher extends BasePublisher {
    public void attach(BaseObserverRole role) {
        observerRoles.add(role);
    }

    @Override
    protected void notifyRoles(String msg) {
        observerRoles.forEach((it) -> {
            it.update(msg);
        });
    }

    @Override
    public void addNewStatus(String msg) {
        // TODO Auto-generated method stub
        notifyRoles(msg);
    }
}
/*
观察者基类
*/
abstract class BaseObserverRole {
    protected BasePublisher statusPublisher;

    /**
     * 观察者数据处理方法。
     * 
     * @description 观察者抽象类的必要方法,通过该方法对属于自己的数据进行处理
     * @author Maple Chan
     * @date: 2020-07-28 22:25:46
     * @params
     * @return
     * @param msg
     */
    abstract void update(String msg);

    /**
     * 订阅发布者方法。
     * 
     * @description 观察者抽象类的必要方法,通过该方法进行订阅数据
     * @author Maple Chan
     * @date: 2020-07-28 22:22:53
     * @params statusPublisher
     * @return
     * @param statusPublisher
     */
    abstract void subscribe(BasePublisher statusPublisher);
}

/**
 * @description: 一个观察者的实现类
 * @modifyContent:
 * @author: Maple Chan
 * @date: 2020-07-28 22:32:05
 * @version: 0.0.1
 */
class AlarmLightRole extends BaseObserverRole {
    private final String tag = "alarm";

    @Override
    public void update(String msg) {
        if (msg.contains(tag)) {
            System.out.println("This is AlarmLightRole message, tag is " + tag);
            System.out.println("AlarmLightRole dealing message: " + msg);
        }
    }

    @Override
    void subscribe(BasePublisher faultStatusPublisher) {
        this.statusPublisher = faultStatusPublisher;
        faultStatusPublisher.attach(this);
    }

}

/**
 * @description: 一个观察者的实现类
 * @modifyContent:
 * @author: Maple Chan
 * @date: 2020-07-28 22:32:05
 * @version: 0.0.1
 */
class DetectIsStopRole extends BaseObserverRole {
    private final String tag = "detect";

    @Override
    public void update(String msg) {
        if (msg.contains(tag)) {
            System.out.println("This is DetectIsStopRole message, tag is " + tag);
            System.out.println("DetectIsStopRole dealing message: " + msg);
        }
    }

    @Override
    void subscribe(BasePublisher faultStatusPublisher) {
        this.statusPublisher = faultStatusPublisher;
        faultStatusPublisher.attach(this);
    }

}
// 输出:
/*
Role1 subscribe an publisher!
Role2 subscribe an publisher!




faultStatusPublisher notify a massage!
This is AlarmLightRole message, tag is alarm
AlarmLightRole dealing message: alarm: new Message of :class javatest.pattern.AlarmLightRole




faultStatusPublisher notify another massage!
This is DetectIsStopRole message, tag is detect
DetectIsStopRole dealing message: detect: new Message of :class javatest.pattern.DetectIsStopRole
*/

通过上述代码,完成了一个由一个发布者发布不同消息,不同的订阅者通过判断传入的消息进行响应的处理。该设计模式充分利用了多态的特性。BaseObserverRole引用不同的实例,在发布者调用notify的时候,将调用BaseObserverRole的update方法,该方法根据不同具体的实例,执行对应的方法。