设计模式-6-观察者

设计模式-6-观察者

简介:被观察者管理着观察者,当被观察者发生变化,主动向观察者发出通知

目的:建立对象之间的依赖关系, 对象发生改变自动通知其他对象,其他对象作出相应的反应

总结:订阅-发布模式

组成: 观察者, 被观察者

实现方式: 1-自定义    2-JDK

一, 自定义方式

1,观察者

package com.design.f.observer.base;
/**
 * 观察者接口
 */
public interface ObserverService {
    
    /**
     * 被观察者发生改变需要观察者执行的动作
     */
    Boolean update();

}
package com.design.f.observer.base;

/**
 * 观察者A
 */
public class ObserverAServiceImpl implements ObserverService {

    @Override
    public Boolean update() {
        System.out.println("收到被观察者的变化    --> 观察者A  -->  相应的处理 ");
        return true;
    }

}
package com.design.f.observer.base;

/**
 * 观察者B
 */
public class ObserverBServiceImpl implements ObserverService {

    @Override
    public Boolean update() {
        System.out.println("收到被观察者的变化    --> 观察者B  -->  相应的处理 ");
        return true;
    }

}

2,被观察者

package com.design.f.observer.base;

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

/**
 * 被观察者
 */
public class Observable {
    
    
    //1-记录观察者
    private List<ObserverService> observers = new ArrayList<ObserverService>();
    public Boolean addObserver(ObserverService observerService){
        return observers.add(observerService);
    }
    
    
    //2-发生改变的动作
    public void changed(){
        System.out.println("被观察者已发生变化   ... ... ");
        notifyObserver();
        
    }
    
    //3-通知观察者
    private void notifyObserver(){
        System.out.println("被观察者开始通知观察者   ... ... ");
        for(ObserverService observerService : observers){
            observerService.update();
        }
    }

}

3,Main

package com.design.f.observer.base;

/**
 * 6-观察者模式
 * 简介:一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式。
 * 用例:文件上传的进度显示,被关注的博主发布新文章通知关注着,小说网站的订阅者在发布新的小说后通知订阅者
 * 
 * 事件驱动模型
 * 观察者更多的强调的是发布-订阅式的问题处理,而事件驱动则更多的注重于界面与数据模型之间的问题
 * 被观察者 = 事件源
 * 观察者     = 监听器
 * 
 * 用例:Tomcat的启动用到的listener监听器,Spring启动添加监听器随着Tomcat的启动IOC容器也开始启动
 */
public class MainTest {
    
    public static void main(String[] args) {
        /**
         * 观察者模式-自定义
         */
        //1-创建观察者
        ObserverService observerA = new ObserverAServiceImpl();
        ObserverService observerB = new ObserverBServiceImpl();
        //2-向被观察者添加观察者
        Observable observed = new Observable();
        observed.addObserver(observerA);
        observed.addObserver(observerB);
        //3-触发被观察者发生改变,通知观察者
        observed.changed();
    }
}

4,Result

被观察者已发生变化   ... ... 
被观察者开始通知观察者   ... ... 
收到被观察者的变化    --> 观察者A  -->  相应的处理 
收到被观察者的变化    --> 观察者B  -->  相应的处理 

 二,JDK实现方式

1,基础用户类

package com.design.f.observer.base;

import java.io.Serializable;
/**
 * 用户
 */
public class User implements Serializable{
    
    private static final long serialVersionUID = 158957714520271405L;
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String toString() {
        return super.toString();
    }
    
}

2,观察者

package com.design.f.observer.base;

import java.util.Observable;
import java.util.Observer;

/**
 * 观察者
 */
public class Reader implements Observer {
    
    //读者用户信息
    private User user;
    
    public Reader(String userName){
        user = new User();
        user.setUserName(userName);
    }
    
    //关注作者
    public void subscriptionWriter(String writerName){
        
        //检查作者是否存在
        if(WriterManager.getInstance().isWriter(writerName)){
            WriterManager.getInstance().getWriter(writerName).addObserver(this);
        }
        
    }
    
    //取消关注
    public void unSubscriptionWriter(String writerName){
        
        //检查作者是否存在
        if(WriterManager.getInstance().isWriter(writerName)){
            WriterManager.getInstance().getWriter(writerName).deleteObserver(this);
        }
    }
    
    //收到被观察者的要执行的动作
    @Override
    public void update(Observable o, Object arg) {
        
        if(o instanceof Writer){
            Writer writer = (Writer) o;
            System.out.println("读者 : " + user.getUserName() + "  收到作者: " + writer.getUser().getUserName() + "  发布的新书: " +writer.getLastBook());
        }
    }
    
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

}

3,被观察者

package com.design.f.observer.base;

import java.util.Observable;
/**
 * 被观察者
 */
public class Writer extends Observable {

    //作者用户信息
    private User user;
    //作者新书
    private String lastBook;
    
    public Writer(String userName){
        
        //初始化用户信息
        user = new User();
        user.setUserName(userName);
        
        //将作者添加到作者管理器中
        WriterManager.getInstance().addWriter(this);
    }
    
    //作者发布新书动作
    public void pushBook(String bookName){
        System.out.println("作者 : " + user.getUserName() + ";   发布了新书: " + bookName + " ... ... ");
        lastBook = bookName;
        
        //设置被观察发生改变的状态,并通知观察者
        setChanged();
        notifyObservers();
    }
    
    
    public String getLastBook() {
        return lastBook;
    }
    public void setLastBook(String lastBook) {
        this.lastBook = lastBook;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    
}

4,观察者管理器

package com.design.f.observer.base;

import java.util.HashMap;
import java.util.Map;

/**
 * 观察者管理器 
 */
public class WriterManager {
    
    //1-作者集合
    private Map<String, Writer> writerMap = new HashMap<String, Writer>();
    
    //2-添加作者
    public void addWriter(Writer writer){
        writerMap.put(writer.getUser().getUserName(), writer);
    }
    
    //3-删除作者
    public void removeWriter(Writer writer){
        writerMap.remove(writer.getUser().getUserName());
    }
    
    //4-获取作者
    public Writer getWriter(String writerName){
        return writerMap.get(writerName);
    }
    
    //5-作者是否存在
    public Boolean isWriter(String writerName){
        return writerMap.containsKey(writerName);
    }
    
    //获取作者集合单例
    private WriterManager(){}
    public static WriterManager getInstance(){
        return WriterManagerInstance.writerManager;
    }
    private static class WriterManagerInstance{
        static WriterManager writerManager = new WriterManager();
    }
    

    public Map<String, Writer> getWriterMap() {
        return writerMap;
    }
    public void setWriterMap(Map<String, Writer> writerMap) {
        this.writerMap = writerMap;
    }

}

5,Main

package com.design.f.observer.base;

/**
 * 6-观察者模式
 * 简介:一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式。
 * 用例:文件上传的进度显示,被关注的博主发布新文章通知关注着,小说网站的订阅者在发布新的小说后通知订阅者
 * 
 * 事件驱动模型
 * 观察者更多的强调的是发布-订阅式的问题处理,而事件驱动则更多的注重于界面与数据模型之间的问题
 * 被观察者 = 事件源
 * 观察者     = 监听器
 * 
 * 用例:Tomcat的启动用到的listener监听器,Spring启动添加监听器随着Tomcat的启动IOC容器也开始启动
 */
public class MainTest {
    
    public static void main(String[] args) {
        
        /**
         * 观察者模式-自定义
         */
//        //1-创建观察者
//        ObserverService observerA = new ObserverAServiceImpl();
//        ObserverService observerB = new ObserverBServiceImpl();
//        //2-向被观察者添加观察者
//        Observable observed = new Observable();
//        observed.addObserver(observerA);
//        observed.addObserver(observerB);
//        //3-触发被观察者发生改变,通知观察者
//        observed.changed();
        
        /**
         * 观察者模式-JDK
         */
        
        //1-创建读者
        Reader readerA = new Reader("读者A");
        Reader readerB = new Reader("读者B");
        Reader readerC = new Reader("读者C");
        Reader readerD = new Reader("读者D");
        
        //2-创建作者
        Writer writerA = new Writer("莫言");
        Writer writerB = new Writer("路遥");
        
        //3-将读者关注到作者
        readerA.subscriptionWriter("莫言");
        readerB.subscriptionWriter("莫言");
        readerC.subscriptionWriter("莫言");
        readerD.subscriptionWriter("莫言");
        readerA.subscriptionWriter("路遥");
        readerB.subscriptionWriter("路遥");
        
        //5-作者发布新书
        writerA.pushBook("平凡的世界");
        writerB.pushBook("悲惨的世界");
        
        //6-读者A取消路遥关注
        readerA.unSubscriptionWriter("路遥");
        writerB.pushBook("十月围城");
    }

}

6,Result

作者 : 莫言;   发布了新书: 平凡的世界 ... ... 
读者 : 读者D  收到作者: 莫言  发布的新书: 平凡的世界
读者 : 读者C  收到作者: 莫言  发布的新书: 平凡的世界
读者 : 读者B  收到作者: 莫言  发布的新书: 平凡的世界
读者 : 读者A  收到作者: 莫言  发布的新书: 平凡的世界
作者 : 路遥; 发布了新书: 悲惨的世界 ... ... 读者 : 读者B 收到作者: 路遥 发布的新书: 悲惨的世界 读者 : 读者A 收到作者: 路遥 发布的新书: 悲惨的世界
作者 : 路遥; 发布了新书: 十月围城 ... ... 读者 : 读者B 收到作者: 路遥 发布的新书: 十月围城