zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式(Observer)

    其实我以前也有学习过设计模式,也写过一些代码。这次在看代码时,发现设计模式使用的泛滥,想想我的设计模式学习的不够扎实,所以重新拾起,把以前没有学习的设计模式学习一遍,把学习过的设计模式在重温一遍。第一篇我选择的是观察者模式。我在项目代码中看到这个模式,项目中的使用大概说一下:服务器与客户端的交互,服务器端的代码使用了观察者模式,作用是:当用户发送请求以后,通过注册的Manager管理类来调用相应的方法处理用户的请求。

    这里做一个报社新闻给用户推送新闻的案例(当报社推送新闻的时候,所有订阅了报社的读者可以阅读报纸):

    方案一:采用Java自带的观察者接口实现,如下:

    首先是报社类,继承了Observable,需要注意的是在通知观察者之前需要setChanged一下,因为notifyObservers()在调用时,需要知道自己的观察者发生了改变,而这个方法是通过Changed变量来判断是否为true,如果不为true,直接return,具体可以查看源码。所以我们需要setChanged,让hasChanged方法返回true。具体可以看notifyObservers()的定义说明

    import java.util.Observable;
    
    public class Publisher extends Observable {
    
    	public void updateNews(String str) {
    		setChanged();
    		notifyObservers(str);
    	}
    }
    


    然后是用户读者:(这里做了2个读者)需要实现Observer接口,并实现接口内部的具体方法update().实现这样的update方法,主要是因为在notifyObservers函数中对这个update方法进行了调用。这也是设计模式的精髓所在。我们可以查看Observable的具体实现,从而知道如何设计一个抽象的观察者。

    import java.util.Observable;
    import java.util.Observer;
    
    
    public class Reader_1 implements Observer{
    
    	@Override
    	public void update(Observable o, Object arg) {
    		// TODO Auto-generated method stub
    		if(arg instanceof String){
    			System.out.println("I'm Reader_1,"+(String)arg);
    		}
    	}
    
    }
    
    import java.util.Observable;
    import java.util.Observer;
    
    
    public class Reader_2 implements Observer{
    
    	@Override
    	public void update(Observable o, Object arg) {
    		// TODO Auto-generated method stub
    		if(arg instanceof String){
    			System.out.println("I'm Reader_2,"+(String)arg);
    		}
    	}
    
    }
    


    然后是我们的测试Main类:需要做的是创建出版社,读者1,读者2。

    读者1,读者2都订阅报社的报纸。第一次推送。

    然后读者1退订报纸,报社第二次推送。

    public class Main {
    	public static void main(String[] args) {
    		Publisher p = new Publisher();
    		Reader_1 r1 = new Reader_1();
    		Reader_2 r2 = new Reader_2();
    		
    		p.addObserver(r1);
    		p.addObserver(r2);
    		
    		System.out.println("当前读者数:"+p.countObservers());
    		System.out.println("第一次推送消息:");
    		p.updateNews("CCTV-5 SportNews");
    		
    		p.deleteObserver(r1);
    		
    		System.out.println("
    当前读者数:"+p.countObservers());
    		System.out.println("第二次推送消息:");
    		p.updateNews("News for Car");
    	}
    }
    


    运行结果:

    当前读者数:2
    第一次推送消息:
    I'm Reader_2,CCTV-5 SportNews
    I'm Reader_1,CCTV-5 SportNews
    
    当前读者数:1
    第二次推送消息:
    I'm Reader_2,News for Car
    

    ==============================================================================================================================

    方案二:自己动手,丰衣足食。我们需要实现的是抽象报社,抽象读者,具体报社,具体读者,外加一个测试函数即可,

    其实跟Java自己实现的观察者接口相差并不多,下面就简单的实现它的基础功能,如下所示:

    思路清晰,写代码:

    package demo;
    
    import java.util.Vector;
    
    public class AbstractPublisher {
    	// 库函数采用的是Vector来实现对注册读者的存储,我们也走大神的路
    	Vector<AbstractReader> vector;
    
    	public AbstractPublisher() {
    		vector = new Vector<AbstractReader>();
    	}
    
    	public boolean addReader(AbstractReader ar) {
    		if (vector.add(ar))
    			return true;
    		return false;
    	}
    
    	public boolean deleteReader(AbstractReader ar) {
    		if (vector.remove(ar))
    			return true;
    		return false;
    	}
    
    	public void notifyReaders(String news) {
    		for (AbstractReader ar : vector) {
    			ar.readNews(news);
    		}
    	}
    }
    
    package demo;
    
    public interface AbstractReader {
    	public void readNews(String news);
    }
    
    package demo;
    
    public class Publisher extends AbstractPublisher {
    	//推送新闻给读者
    	public void pushNews(String news) {
    		notifyReaders(news);
    	}
    }
    
    package demo;
     
    
    public class Reader_Joy implements AbstractReader{
    
    	@Override
    	public void readNews(String news) {
    		// TODO Auto-generated method stub
    		System.out.println("I'm Reader_Joy " + news);
    	}
    
    }
    
    package demo;
    
    public class Reader_Tom implements AbstractReader{
    
    	@Override
    	public void readNews(String news) {
    		// TODO Auto-generated method stub
    		System.out.println("I'm Reader_Tom "+news);
    	}
    
    }
    



    package demo;
    
    public class Main {
    	public static void main(String[] args) {
    		Publisher p = new Publisher();
    		Reader_Joy joy = new Reader_Joy();
    		Reader_Tom tom = new Reader_Tom();
    		p.addReader(joy);
    		p.addReader(tom);
    		System.out.println("第一次推送消息:");
    		p.pushNews("News Of Game");
    		
    		p.deleteReader(joy);
    		System.out.println("第二次推送消息:");	
    		p.pushNews("News Of City");
    	}
    }
    


    运行结果:

    第一次推送消息:
    I'm Reader_Joy News Of Game
    I'm Reader_Tom News Of Game
    第二次推送消息:
    I'm Reader_Tom News Of City
    

    基本的代码实现就是这样,也许还有错误,但是观察者的基本思想就此理清楚了。

    核心部分:1)报社如何存储注册的读者

    2)报社如何通知注册的读者

    3)如何使用接口和继承的方式组织结构。

    项目源代码:http://www.kuaipan.cn/file/id_132802506211221411.htm?source=1

  • 相关阅读:
    css js 解除网页无法选择进而复制的限制,bd文库无法复制
    Git命令简记
    DDD基本概念-未完成
    多线程隙-IO模型(BIO、NIO、AIO)
    RabbitMQ笔记-保证消息队列高可用
    关于fiddler手机抓包
    spring控制反转是谁在何时何地反转给谁?依赖注入??
    Cookie、Session、Token的区别
    详解Redis中两种持久化机制RDB和AOF
    Java中线程池的抛出策略、阻塞队列、内存溢出
  • 原文地址:https://www.cnblogs.com/vokie/p/3602078.html
Copyright © 2011-2022 走看看