观察者模式

对于通知事件可以分成三个部分:事件监听、事件处理和具体的业务流程
观察者模式
   观察者模式,我第一次听到这个词的时候也莫名其妙
,为什么叫观察者模式,观察者模式是干什么的,哪里
会用这个东西?还23种设计模式,起名字都这么抽象,
干嘛的也不知道,名字起的也莫名其妙,抽象的很,一
点也没有理科生的逻辑思维和理性化。

    虽然这么说,但是我还是去网上找找一些文章看看
什么是观察者模式,虽不至于一下子就明白了,但是懂
一些边边角角也好。

    我先查了一下类图看看观察者模式到底长什么样。
    

1157683-20180630210022084-1133176611.png

从网上找了一个图,有NumberGenerator、Observer、
RandomNumberGenerator、DigitalObserver、
GraphObserver组成。Observer是一个接口,这个接
口定义了一个方法update。然后DigitalObserver
和GraphObserver实现了Observer的接口。有
NumberGenerator中引入了Observer接口,并定义了
notifyObserver、execuate、getNumber、add、
remove方法,然后RandomNumberGenerator继承了
NumberGenerator。

这是啥意思啊,我看着也一脸蒙,Observer是观察
者?DigitalObserver和GraphObserver实现了观察
者,他们实现观察者干什么?为什么NumberGenera
tor要引入Observer?

观察者到底是什么?我想到了两个人打架,旁边肯
定会聚集一群人过来看,有的看看指指点点,有的
看看说三道四,有的看看要拿手机拍照,有的看看
要上去拉架,有的看看要打110报警。这里面的观察
者难道就是这些聚集起来的群众,然后有的人做这
些、有的人做哪些,他们的这些行为就是他们看见
这个事情之后做出来的行为。被称为观察者行为,
他们看到的就是观察者事件,遇到这样的事件做出
这样的行为。这就是观察者模式吗?我感觉我已经
通透了,然后又看了看上面的类图,恍然大悟,原
来这就是观察者模式,我天赋真高。

然后我就想这个东西好像在系统中的用处好像很多
把,比如说,系统中如果出现用户登录,就记录登
录信息,变更用户状态,调出用户历史记录,如果
用户修改个人信息,要通知系统修改用户数据记录
,如果由缓存信息,也要修改缓存记录,我想想,
原来这么多地方都可以使用观察者模式,我真是太
聪明了。

但是好像系统里面这些地方都不是使用观察者模式
,好像都是直接修改,观察者好像是,我看到这个
事件,我要做哪些事情,对不对。按理来说事件发
生,跟事件结果没有直接关系,都是通过其他观察
者的反应产生的结果,跟当时的事件关联者应该是
没有关系的,产生的结果可能会有直接或者间接的
关系。所以修改个人用户信息,产生的直接结果就
是要修改数据库的信息,产生的间接结果可能是其
他服务知道你修改了个人信息,可能要去记录个人
修改信息日志,或者是记录审计日志这个事件是间
接事件,这种是观察者直接产生的结果。因为记日
志这个事情不是事件直接导致的结果,而且由观察
者直接产生的结果。

然后我根据这个描述我想到的写个类来描述一下上 
面的这个示例,首先需要定义一下UserMapper类,
这个用于持久用户信息,然后还有两个类,一个是U
serLog类用于记录用户个人信息变更,上面的类都
是执行记录日志的类,肯定还需要有一个观察者,
这个观察者用于观察用户个人信息的变更UserEditO
bserver。我们根据这个来写一下代码

Class UserMapper{

    UserEditObserver userEditObserver;
    

    void insert(User user){
       /**
        * 持久化用户信息
        */   
        
        // 这个观察者发现如果存在用户信息变更就
        // 通知UserLog记录一下当前修改的个人信息
        userEditObserver.notify(user);
    }
}

Class UserEditObserver{
    
    UserLog userLog;
    
    // 插入修改之后的用户信息日志
    void notify(User user){
        userLog.insert(user);
    }
}
这个好像是写完了,但是我仔细看了一下,怎么跟上面的
类图不一样呢。哪里有问题呢?原来Observer是个接口,		 
下面有两个实现呢,为什么要定义接口呢?我想了想是
不是因为如果只是修改用户信息记录日志可能不能只满足一
个观察者的功能,按理来说观察者肯定会存在1~n个,
所以肯定要由一个接口存在,每个观察者看到这个事件之
后,产生的结果都是不一样的。原来如此,那我在修改一下代码吧


class UserMapper {

    /**
     * 引入观察者类
     */
    Observer userEditObserver;

    void insert(User user) {
        /**
         * 持久化用户信息
         */

        // 这个观察者发现如果存在用户信息变更就
        // 通知UserLog记录一下当前修改的个人信息
        userEditObserver.notify(user);
    }
}

/**
 * 定义一个观察者的接口
 */
interface Observer {
    void notify(User user);
}

/**
 * 实现观察者模式
 */
class UserEditObserver implements Observer {

    UserLog userLog;

    // 插入修改之后的用户信息日志
    public void notify(User user) {
        userLog.insert(user);
    }
}

/**
 * 用户信息
 */
class User {
}

/**
 * 用户日志类
 */
interface UserLog {
    void insert(User user);
}

看了一下这次应该差不多了吧,仔细一看,还是有些问题
,我的观察者写好了,那观察者看到这个事件了,肯定要
有反应才行啊,那最起码得有行为才行,什么是行为呢,
就是这个事件引起的观察者的行为,我的代码里面只有调
用观察者接口,而接口对应的观察者没有。那是不是
`Observer userEditObserver = new UserEditObserver();`
就可以解决这个事情了,但是刚才不是说了么,会有很多
个观察者了么。我想到一种方式,第一种就是把实现
·Observer·的类都通知一下,第二种方式就是把固定某
些实现类通知一下。然后我们想一下怎么实现这两种想法。
但是想想第一种方式,如果有一个实现类就通知一下,
那真是太可怕了,万一这个类废弃了但是忘记删除了呢?
该怎么办?这种想法肯定是不行的,还是第二种方式比
较保险一些,而且我看了一下类图原来那个·NumberGenerator·
是专门管理观察者的,我们重新实现一下代码,如下:

class UserMapper {
    
    ObserverManager observerManager ;
    
    void init() {
        observerManager.add(new UserEditObserver());
    }

    void insert(User user) {
        /**
         * 持久化用户信息
         */

        // 这个观察者发现如果存在用户信息变更就
        // 通知UserLog记录一下当前修改的个人信息
        observerManager.notifyObserver(user);
    }
}

/**
 * 观察者管理器
 */
class ObserverManager{

    /**
     * 观察者列表,因为会存在0-n观察者
     */
    List<Observer> observers = new ArrayList<>();

    /**
     * 插入观察者类
     * @param observer 观察者接口
     */
    public void add(Observer observer ){
        observers.add(observer);
    }

    /**
     * 删除观察者
     * @param observer
     */
    public void remove(Observer observer){
        observers.remove(observer);
    }

    /**
     * 通知观察者事件已经发生,让观察者发生行为
     * @param user
     */
    public void notifyObserver(User user){
        observers.forEach(e -> e.notify(user));
    }
}

/**
 * 定义一个观察者的接口
 */
interface Observer {
    void notify(User user);
}

/**
 * 实现观察者模式
 */
class UserEditObserver implements Observer {

    UserLog userLog;

    // 插入修改之后的用户信息日志
    public void notify(User user) {
        userLog.insert(user);
    }
}

/**
 * 用户信息
 */
class User {
}

/**
 * 用户日志类
 */
interface UserLog {
    void insert(User user);
}
这里面加了一个·ObserverManager·用于管理观察者,如果存
在事件就通知观察者执行行为。OK这个观察者到这里就基本
结束了,还有人说,有的观察者可能当时不执行行为,到中午
或者是下午,或者是第二天在执行这个操作。或者有的观察者
是同时看到这个事件的,他们是同步的(同时执行的),还有
可能会影响事件结果等等,这个都是观察者行为处理方式。可
以根据观察者行为进行处理。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值