系列文章目录
[0]设计模式-设计原则
[1]设计模式-策略模式
[2]设计模式-观察者模式(手动实现)
[3]设计模式-观察者模式(内置模型)
[4]设计模式-观察者模式(JFrame)
[5]设计模式-装饰者模式(初学缺陷版)
[6]设计模式-装饰者模式(进阶完善版)
文章目录
前言
随着业务的复杂以及扩展,当我们需要某一个动作创建后,其他订阅的单元都能收到这个信息,那么观测者模式就能很好的解决这个问题。
一、观察者模式是什么?
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态的时候,它的所有依赖者都会收到通知并自动更新。
二、核心代码
1.创建数据中心主题
代码如下(示例):提供一个subject,可以对订阅者发布数据,管理订阅者。代码延续上一遍,我打算用一个融合的代码贯通所有设计模式。
/**
* 数据中心主题.<br>
*
* <p>
* 对订阅者的注册,移除,通知
* <P>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public interface IDataCenterSubject {
void registObserver(IDataCenterObserver o);
void removeObserver(IDataCenterObserver o);
void notifyObserver();
}
2.创建数据中心观察者
代码如下(示例):创建观察者接口,主要的思路是我们要接收数据中心推来的哪些数据来进行定义,观察者可以有很多,代码往下阅读。
/**
* 数据中心观察者.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public interface IDataCenterObserver {
/**
* 接收主题推送来的数据.
*
* @param dataHandler
*/
void recieveRobot(Robot r);
}
3.实现数据中心
代码如下(示例):数据中心的功能实现,除了实现主题接口的基本功能,还有接收最新的机器人数据,并发送给每个各个地区订阅了的数据中心主题的数据中心。
/**
* 数据中心实现.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public class DataCenter implements IDataCenterSubject {
/**
* 观察者集合.
*/
private ArrayList<IDataCenterObserver> observers;
/**
* 机器人数据.
*/
private Robot r;
public DataCenter() {
observers = new ArrayList<IDataCenterObserver>();
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataCenterSubject#registObserver(com.study.designMode.observerMode.IDataCenterObserver)
*/
@Override
public void registObserver(IDataCenterObserver o) {
observers.add(o);
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataCenterSubject#removeObserver(com.study.designMode.observerMode.IDataCenterObserver)
*/
@Override
public void removeObserver(IDataCenterObserver o) {
int index = observers.indexOf(o);
if (index >= 0) {
observers.remove(o);
}
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataCenterSubject#notifyObserver()
*/
@Override
public void notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
IDataCenterObserver observer = observers.get(i);
observer.recieveRobot(r);
}
}
public void dataCenterChanged() {
notifyObserver();
}
public void publishRobot(Robot r) {
this.r = r;
dataCenterChanged();
}
}
4.创建多个数据中心
代码如下(示例):当发现多个数据中心除了订阅主题,接收主题消息之外,还需要进行数据展示 。于是抽出一个接口做数据处理。
/**
* 华北数据中心.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public class DataCenterNorthChina implements IDataHandler, IDataCenterObserver {
/**
* 数据主题.
*/
private IDataCenterSubject dataCenter;
/**
* 接收最新发布的机器人.
*/
private Robot r;
/**
* 初始化订阅数据中心.
*
* @param dataCenter
*/
public DataCenterNorthChina(IDataCenterSubject dataCenter) {
this.setDataCenter(dataCenter);
dataCenter.registObserver(this);
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataCenterObserver#active(com.study.designMode.observerMode.IDataHandler)
*/
@Override
public void recieveRobot(Robot r) {
this.r = r;
display();
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataHandler#run()
*/
@Override
public void display() {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println("华南展示最新机器人\n" + r.getName());
r.getPowerConsumptionMode().myMethod();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
}
/**
* 获取dataCenter.
*
* @return the dataCenter
*/
public IDataCenterSubject getDataCenter() {
return dataCenter;
}
/**
* 设置dataCenter.
*
* @param dataCenter
* the dataCenter to set
*/
public void setDataCenter(IDataCenterSubject dataCenter) {
this.dataCenter = dataCenter;
}
}
/**
* 华南数据中心.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public class DataCenterSouthChina implements IDataHandler, IDataCenterObserver {
/**
* 数据中心Subject.
*/
private IDataCenterSubject dataCenter;
/**
* 接收最新发布的机器人.
*/
private Robot r;
/**
* 初始化订阅数据中心.
*
* @param dataCenter
*/
public DataCenterSouthChina(IDataCenterSubject dataCenter) {
this.setDataCenter(dataCenter);
dataCenter.registObserver(this);
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataCenterObserver#active(com.study.designMode.observerMode.IDataHandler)
*/
@Override
public void recieveRobot(Robot r) {
this.r = r;
display();
}
/**
* {@inheritDoc}
*
* @see com.study.designMode.observerMode.IDataHandler#run()
*/
@Override
public void display() {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println("华北展示最新机器人\n" + r.getName());
r.getPowerConsumptionMode().myMethod();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
}
/**
* 获取dataCenter.
*
* @return the dataCenter
*/
public IDataCenterSubject getDataCenter() {
return dataCenter;
}
/**
* 设置dataCenter.
*
* @param dataCenter
* the dataCenter to set
*/
public void setDataCenter(IDataCenterSubject dataCenter) {
this.dataCenter = dataCenter;
}
}
5.创建数据处理接口
代码如下(示例):接收主题消息之外,还需要进行数据展示 。于是抽出一个接口做数据处理。也可以集成更多的数据处理功能,比如不同地区可以浮动价格之类。
/**
* 数据处理.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
@FunctionalInterface
public interface IDataHandler {
public void display();
}
6.创建测试类
代码如下(示例):简单的观察者模型就建立完成了,先测试一个数据中心订阅的结果。
/**
* 观察者模式测试.<br>
*
* @author likang5 <br>
* @version 1.0.0 2022年5月17日<br>
* @see
* @since JDK 1.5.0
*/
public class ObserverTest {
public static void main(String[] args) {
// 创建数据中心
DataCenter dataCenter = new DataCenter();
// 订阅数据中心
new DataCenterSouthChina(dataCenter);
// new DataCenterNorthChina(dataCenter);
// 生产机器人
Robot r1 = new Robot();
r1.setName("我是机器人一号 !");
r1.setPowerConsumptionMode(new LowPowerConsumptionMode());
// 数据中心发布机器人
dataCenter.publishRobot(r1);
// 生产机器人
// Robot r2 = new Robot();
// r2.setName("我是机器人二号 !");
// r2.setPowerConsumptionMode(new HightPowerConsumptionMode());
//
// dataCenter.publishRobot(r2);
}
}
代码如下(示例):发布两个机器人,代码上面都有,直接贴图。
代码如下(示例):有两个数据中心订阅了主题,发布两个机器人。
总结
以上就是对观察者模式的简单应用,了解的同学可能知道java工具提供了对应的模式,当前是手写的subject,手写的更加灵活。下一篇也会发布一个短篇,是使用工具来进行实现的,有兴趣的可以看一下。