设计模式入门:观察者模式

原文地址:http://te-amo.site/user/article/info/ARTICLE20180407063327367
文章中部分定义和解释性文字,都是引用百度百科,主要的代码及场景应用为本人原创

一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知

场景:我在设计我个人网站时,有一个留言功能。其中有一个需求是:当管理员在后台回复留言后,要做三件事(1)更改数据库,将处理完的留言标记为已处理(2)将答复内容通过邮件发送给留言人(3)给管理员一个提示告诉他,邮件已经发出。

其实面对这个场景,完全可以使用顺序的方式来完成这一系列操作,先更新数据库,再发送邮件,最后给管理员消息提示。但是这种设计不容易拓展与维护,如果以后需要增加新的操作,是需要修改整个逻辑结构。鉴于这个三个操作没有严格的关联要求,所以可以使用观察者模式。

设计
这里写图片描述

构成

  • 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。(Observer)
  • 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。(LeaveMessageSubject)
  • 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。(ChangeDB,NotifyMessage,ReplyEmail)

实现

代码地址:https://github.com/telundusiji/designpattern

Observer 抽象观察者

public interface Observer {
    void update(Message message);
}

ChangeDB 具体观察者,更新数据库

@Slf4j
public class ChangeDB implements Observer {
    public void update(Message message) {
        log.info("留言:{},{},{},在数据库中更新!",message.id,message.name,message.content);
    }
}

NotifyMessage 具体观察者 给管理员进行消息提示

@Slf4j
public class NotifyMessage implements Observer{
    public void update(Message message) {
        log.info("留言:{},{},{},已通过邮件回复",message.id,message.name,message.content);
    }
}

ReplyEmail 具体观察者 发送邮件

@Slf4j
public class ReplyEmail implements Observer {
    public void update(Message message) {
        log.info("留言:{},{},{},发送邮件...",message.id,message.name,message.content);
    }
}

LeaveMessageSubject 具体被观察者 message更新时通知所有观察者

public class LeaveMessageSubject {
    List<Observer> observers;
    private Message message;
    public LeaveMessageSubject() {
        observers = new ArrayList<Observer>();
    }

    public void addObserver(Observer observer){
        observers.add(observer);
    }

    public boolean removeObserver(Observer observer){
        return observers.remove(observer);
    }

    public void notifyObserver(){
        for(Observer o : observers){
            o.update(message);
        }
    }

    public void setMessage(Message message) {
        this.message = message;
        notifyObserver();
    }
}

Message 留言实体

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Message {
    int id;
    String name;
    String email;
    String content;
}

经典应用

在servlet中Listener就是使用观察者模式

  • EventListener 抽象的观察者
  • ServletContextAttributeListener,ServletRequestAttributeListener…都是具体观察者
  • HttpServletRequest…可以认为是具体被观察者

例如:当HttpServletRequest 调用setAttribute方法时,就会去调用notifyAttributeAssigned方法,此方法会创建对应的事件对象,然后通知所有观察改事件的观察则进行更新

具体细节可以去看源码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章