zoukankan      html  css  js  c++  java
  • 【设计模式】观察者模式

    From: https://liudongdong1.github.io/

    察者模式又被称为发布订阅(Publish/Subscribe)模式,属于对象行为型模式。它定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,它的所有观察者都会收到通知并自动更新相关内容。主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知.

    核心类说明:

    • Subject:抽象主题,即被观察对象,本身维护一个观察者集合。
    • Observer:抽象观察者,根据主题状态变化做出相应反应,本身维护一个主题的引用。

    注意事项:

    • Java 中已经有了对观察者模式的支持类。
    • 避免循环引用。
    • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
    .1. 自定义观察者

    //定义主题
    public interface Subject {
        void registerObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObserver();
    }
    public class Blog implements Subject{
     	//存储已定阅的读者
    	private ArrayList observerList;
    	//这是更新的文章
    	private String news;
    	
    	public Blog(){
    		observerList = new ArrayList();
    	}
    	@Override
    	public void registerObserver(Observer observer){
    		observerList.add(observer);
    	}
    	@Override
        public void removeObserver(Observer observer){
        	int index = observerList.indexOf(observer);
        	//不要忘记如果observer没有订阅的话会返回-1
        	if(index>=0){
        		observerList.remove(index);
        	}
        }
        @Override
        public void notifyObserver(Object arg){
        	 for(int i=0;i<observerList.size();i++){
                Observer observer = (Observer)observerList.get(i);
                observer.update(this,arg);
            }
        }
        //文章更新时进行
        public void newsChanged(){
        	notifyObserver(this.news);
        }
    	//模拟博客更新文章
    	public void setNews(){
    		news = "观察者模式";
    		notifyObserver();
    	}
        
    }
    //观察者
    public interface Observer {
    	//因为一个观察者可能订阅了多个主题,所以需要确定是哪个主题
        void update(Subject subject,Object arg);
    }
    public class Reader implements Observer{
    	private String news;
        //存储主题,以方便之后的退订操作
        private Subject subject;
        public Reader(Subject subject){
            this.subject = subject;
            //读者订阅
            subject.registerObserver(this);
        }
    
        @Override
        public void update(Subject subject, Object arg) {
        //确定主题身份
            if(subject instanceof Blog){
                news = (String)arg;
            }
            //读者阅读博客
            read(this.news);
        }
    	//该方法模拟读者阅读
        public void read(String news){
            System.out.println(news);
        }
        //退订
        public removeSubscript(){
        	this.subject.removeObserver(this);
        }
    }
    public static void main(String[] args) {
            Blog blog = new Blog();
            //读者订阅博客
            Reader reader = new Reader(blog);
            //博客更新
            blog.setNews();
    }
    
    .2. java自带类

    public class NewspaperOffice extends Observable {
        private String news; // 报社新闻内容
    
        //注意与自己实现的不同处,添加观察者放在超类中处理
        public NewspaperOffice() {}
    
        public void setNews(String news) {
            this.news = news;
            newsChanged();
        }
        public String getNews() {
            return news;
        }
        // 内容改变时,通知观察者
        public void newsChanged() {
            setChanged();
            notifyObservers(); 
        }
    }
    public class Eric implements Observer {
        private Observable observable;  // 主题的引用
        private String news;
        
        public Eric(Observable observable){
            this.observable = observable;
            this.observable.addObserver(this); // 把此对象添加为观察者
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof NewspaperOffice) {
                NewspaperOffice newspaperOffice = (NewspaperOffice) o;
                this.news = newspaperOffice.getNews();
                showNews(); //更新信息后显示信息
            }
        }
    
        public void showNews(){
            System.out.println("Eric: "+news);
        }
    }
    public class Shealtiel implements Observer {
        private Observable observable; //主题的引用
        private String news;
    
        public Shealtiel(Observable observable){
            this.observable = observable;
            this.observable.addObserver(this); //把此对象添加为观察者
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof NewspaperOffice) {
                NewspaperOffice newspaperOffice = (NewspaperOffice) o;
                this.news = newspaperOffice.getNews();
                showNews(); //更新信息后显示信息
            }
        }
    
        public void showNews(){
            System.out.println("Shealtiel: "+news);
        }
    }
    public class Demo {
        public static void main(String[] args) {
            //实例化报社类(被观察者)
            NewspaperOffice newspaperOffice = new NewspaperOffice();
            //实例化订阅者类(观察者)
            Eric eric = new Eric(newspaperOffice);
            Shealtiel shealtiel = new Shealtiel(newspaperOffice);
    
            //报社更新信息,自动会通知相应的观察者
            System.out.println("报社更新第一条信息,注意观察者接受的信息:");
            newspaperOffice.setNews("This is the first news!");
            System.out.println("
    报社更新第二条信息,注意观察者接受的信息:");
            newspaperOffice.setNews("This is the second news!");
    
            //eric对象取消订阅报纸新闻,则此后的新闻信息将不会通知eric
            System.out.println("
    Eric取消订阅新闻信息");
            newspaperOffice.deleteObserver(eric);
    
            System.out.println("报社更新第三条信息,注意此时观察者数量:");
            newspaperOffice.setNews("This is the third news!");
        }
    }
    
  • 相关阅读:
    迷宫广搜
    通过地址获取百度地图经纬度
    图片上传存储数据库
    spring boot加载配置文件的顺序
    阿里 短信认证
    spring boot properties文件与yaml文件的区别
    springboot pom问题及注解
    手机短信认证
    获取class对象的三种方法以及通过Class对象获取某个类中变量,方法,访问成员
    关于mysql优化问题
  • 原文地址:https://www.cnblogs.com/liu-dongdong/p/15117646.html
Copyright © 2011-2022 走看看