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

        观察者模式:
        试想,在电子商务网站上,一个用户看中了一件一份,但是当时衣服的价格太贵,你需要将衣服收藏,以便等衣服降价时自动通知该用户。这里就是典型的观察模式的例子。
        1.观察者模式的定义:
           定义了一种对象之间的依赖关系,当一个对象(主题)发生改变时,它所有的依赖者(观察者)会收到主题状态改变的通知,并更新自己的状态。

           观察者模式让主题和观察者松耦合。主题不知道观察者的实现细节;任何时候在增加观察者的时候,可以随时增加,而不需要改变主题的代码,当然删除观察者也是一样。在开始的例子中,衣服便是主题(Subject),用户便是观察者(Observer),用户将衣服加收藏的过程便是观察者在主题注册那里的过程。

        2.观察者模式的类图:

         

         3.java提供了内置的观察者模式:Observer接口和Observerable类;为了理解观察模式,先不用这个内置方法,先用常规的方法实现以下上述例子:

    package observer;
    //主题接口
    public interface Subject {
    
    	public void addObserver(Observer observer);
    	public void deleteObserver(Observer observer);
    	public void notifyObserver();
    }
    

    package observer;
    
    //观察者接口
    public interface Observer {
    
    	public double getOldPrice();
    	public void update(double price);
    }
    

    package observer;
    /*
     * 具体的主题,concrete subject
    */
    import java.util.ArrayList;
    import java.util.List;
    public class ClotheSubject implements Subject{
    
    	List<Observer> observers ;
    	double price;
    	public ClotheSubject()
    	{
    		observers = new ArrayList<>();
    	}
    	@Override
    	public void addObserver(Observer observer) {
    		// TODO Auto-generated method stub
    		observers.add(observer);
    	}
    
    	@Override
    	public void deleteObserver(Observer observer) {
    		// TODO Auto-generated method stub
    		int index = (int)observers.indexOf(observer);
    		if(index >= 0)
    		observers.remove(index);
    	}
    
    	@Override
    	public void notifyObserver() {
    		// TODO Auto-generated method stub
    		for(int i = 0;i < observers.size();i++)
    		{
    			Observer observer = (Observer)observers.get(i);
    			observer.update(price);
    		}
    	}
    	
    	public void setPrice(double price)
    	{
    		this.price = price;
    		notifyObserver();
    	}
    
    	
    }
    
    package observer;
    
    public class ClotheObserver implements Observer{
    
    	Subject subject;
    	double price = 100.00d;//原始价格
    	public ClotheObserver(Subject subject)
    	{
    		this.subject = subject;
    		subject.addObserver(this);
    	}
    	@Override
    	public void update(double price) {
    		// TODO Auto-generated method stub
    		if(price<this.getOldPrice())
    		System.out.println("您上次看中衣服的价格变为:"+price+",请抓紧购买!");
    		this.price = price;
    	}
    	@Override
    	public double getOldPrice() {
    		// TODO Auto-generated method stub
    		return price;
    	}
    
    }
    
    测试代码:
    package observer;
    
    public class Client_test {
    
    	public static void main(String args[])
    	{
    		ClotheSubject clothe_subject = new ClotheSubject();
    		Observer clothe_observer = new ClotheObserver(clothe_subject);
    		clothe_subject.setPrice(10.00d);
    		clothe_subject.setPrice(90.00d);
    		clothe_subject.setPrice(20.00d);
    	}
    }
    

          4.java自身提供的内置观察者模式:java.util提供了observer接口和Observerable类,对象只需要实现观察者接口,便可以成为观察者,然后调用Observerable的addObserver方法,便加入主题中。下面是用内置观察者模式重新修改上例代码:

          主题类:

    package observer;
    /*
     * 具体的主题,concrete subject
    */
    import java.util.Observable;
    public class ClotheSubject extends Observable{
    
    	double price;
    	public ClotheSubject()
    	{
    	}
    	public void priceChanged()
    	{
    		setChanged();
    		notifyObservers();//Observable中的方法,会调用观察者的update方法
    	}
    	
    	public void setPrice(double price)
    	{
    		this.price = price;
    		priceChanged();
    	}
    
    	public double getPrice()
    	{
    		return price;
    	}
    }
    
    观察者类:

    package observer;
    import java.util.Observable;
    import java.util.Observer;
    public class ClotheObserver implements Observer{
    
    	Observable observerable;
    	double price = 100.00d;
    	public ClotheObserver(Observable observerable)
    	{
    		this.observerable = observerable;
    		//将自己注册为观察者
    		observerable.addObserver(this);
    	}
    	@Override
    	public void update(Observable o, Object arg) {
    		// TODO Auto-generated method stub
    		if(o instanceof ClotheSubject)
    		{
    			ClotheSubject clothesubject = (ClotheSubject)o;
    			if(price > clothesubject.getPrice())
    				display(clothesubject.getPrice());
    			this.price = clothesubject.getPrice();
    		}
    	}
    	
    	public void display(double price)
    	{
    		System.out.println("您上次看中衣服的价格变为:"+price+",请抓紧购买!");
    	}
    	
    }
    
    测试代码:

    package observer;
    
    public class Client_test {
    
    	public static void main(String args[])
    	{
    		ClotheSubject clothe_subject = new ClotheSubject();
    		ClotheObserver clothe_observer = new ClotheObserver(clothe_subject);
    		clothe_subject.setPrice(90.00d);
    		clothe_subject.setPrice(80.00d);
    	}
    }



  • 相关阅读:
    黑鲨2无限重启 把竞技按钮调到最上
    绿联 电池
    阿里云
    Centos 8 搭建时钟服务器
    CentOS8系统时间同步解决方法
    解决问题的人干活快的人
    【海通国际】Joe Lowry(Mr. Lithium)谈全球电池原材料供应危机
    Linux 实验楼
    用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程
    【随笔】阿里云修改DNS
  • 原文地址:https://www.cnblogs.com/sunp823/p/5601411.html
Copyright © 2011-2022 走看看