java设计模式——观察者模式

1.观察者模式两种模式

(1)推模型:目标对象主动向观察者推送目标的详细信息 ; 推送的信息通常是目标信息的全部或部分信息

(2)拉模型:目标对象在通知观察者的时候,只传递少量信息 ;如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据;一般这种模型的实现中,会把目标对象自身通过update方法传递给观察者。

 比较

推模型是假定目标对象知道观察着需要的数据

拉模型是目标对象不知道观察着具体需要什么数据,因此把自身传给观察者,由观察者来取值


2.

观察者模式的优点:

(1)观察者模式实现了观察者和目标之间的抽象耦合

(2)观察者模式实现了动态联动

(2)观察者模式支持广播通信


3.

观察者模式的缺点:

(1)可能会引起无谓的操作


4.建议在以下情况下使用观察者模式

(1)当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化

(2)如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该 有多少对象需要被连带改变

(3) 当一个对象必须通知其他的对象,但是你又希望这个对象和其他的被通知的对象是松散耦合的


例1: 拉模型

package observer_pull;
import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式
 * 抽象目标对象,它知道观察它的观察者,并提供添加和删除观察者的接口
 * */
public class Subject {

	//用来保存观察者
	private List<Observer> observers = new ArrayList<Observer>();
	
	/**
	 * 添加观察者
	 * */
	public void add(Observer observer)
	{
		observers.add(observer);
	}
	/**
	 * 删除观察者
	 * */
	public void remove(Observer observer)
	{
		observers.remove(observer);
	}
	
	/**
	 *向所有观察者发送消息
	 * */
	public void notifyObservers(String content)
	{
		for(Observer observer : observers)
		{
			observer.update(content);
		}
	}
}

package observer_pull;
/**
 * 观察者模式
 * 观察者接口
 * */
public interface Observer {

	public void update(String state);
}

package observer_pull;
/**
 * 观察者模式
 * 具体目标对象 ,负责将有关状态存入到对应观察者对象中
 * */
public class ConcreteSubject extends Subject {
	
	//被观察对象的状态
	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
		this.notifyObservers(state);
	}
	
	
}

package observer_pull;
/**
 * 观察者模式
 * 具体观察者对象
 * */
public class ConcreteObserver implements Observer{

	//观察者状态
	private String observerState;
	
	
	
	public ConcreteObserver(String observerState) {
		super();
		this.observerState = observerState;
	}

	@Override
	public void update(String state) {
		// TODO Auto-generated method stub
		System.out.println(observerState+":"+state);
	}

}

package observer_pull;


public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ConcreteSubject subject = new ConcreteSubject();
		ConcreteObserver observer1 = new ConcreteObserver("观察者a");
		ConcreteObserver observer2 = new ConcreteObserver("观察者b");
		subject.add(observer1);
		subject.add(observer2);
		subject.setState("123");
		
	}

}

输出结果:

观察者a:123

观察者b:123

例2 : 推模型

package observer_push;
import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式
 * 抽象目标对象,它知道观察它的观察者,并提供添加和删除观察者的接口
 * */
public class Subject {

	//用来保存观察者
	private List<Observer> observers = new ArrayList<Observer>();
	
	/**
	 * 添加观察者
	 * */
	public void add(Observer observer)
	{
		observers.add(observer);
	}
	/**
	 * 删除观察者
	 * */
	public void remove(Observer observer)
	{
		observers.remove(observer);
	}
	
	/**
	 *向所有观察者发送消息
	 * */
	public void notifyObservers()
	{
		for(Observer observer : observers)
		{
			observer.update(this);
		}
	}
}

package observer_push;
/**
 * 观察者模式
 * 观察者接口
 * */
public interface Observer {

	public void update(Subject subject);
}

package observer_push;
/**
 * 观察者模式
 * 具体目标对象 ,负责将有关状态存入到对应观察者对象中
 * */
public class ConcreteSubject extends Subject {
	
	//被观察对象的状态
	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
		this.notifyObservers();
	}
	
	
}

package observer_push;
/**
 * 观察者模式
 * 具体观察者对象
 * */
public class ConcreteObserver implements Observer{

	//观察者状态
	private String observerState;
	
	
	
	public ConcreteObserver(String observerState) {
		super();
		this.observerState = observerState;
	}



	@Override
	public void update(Subject subject) {
		// TODO Auto-generated method stub
		System.out.println(observerState+":"+((ConcreteSubject)subject).getState());
	}

}

package observer_push;

import java.util.Observer;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ConcreteSubject subject = new ConcreteSubject();
		ConcreteObserver observer1 = new ConcreteObserver("观察者1");
		ConcreteObserver observer2 = new ConcreteObserver("观察者2");
		subject.add(observer1);
		subject.add(observer2);
		subject.setState("123");
		
	}

}

输出结果:

观察者1:123

观察者2:123

例3: jdk实现

package observer_jdk;

import java.util.Observable;

/**
 * 目标对象
 * */
public class ConcreteSubject extends Observable {
	
	private String content ;

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
		//调用notifyObservers之前必须调用
		this.setChanged();
		//通知所有的观察者
		this.notifyObservers(content);
	}
	
	

}
</pre><p></p><pre name="code" class="java">package observer_jdk;

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

public class ConcreteObserver implements Observer {

	private String state;
	
	
	
	public ConcreteObserver(String state) {
		super();
		this.state = state;
	}

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		System.out.println(state+" 通过拉模式获得内容:"+((ConcreteSubject)o).getContent());
		System.out.println(state+" 通过推模式获得内容:"+arg);
	}

}

package observer_jdk;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		ConcreteSubject subject = new ConcreteSubject();
		ConcreteObserver observer1 = new ConcreteObserver("观察者A");
		ConcreteObserver observer2 = new ConcreteObserver("观察者B");
		
		subject.addObserver(observer1);
		subject.addObserver(observer2);
		
		subject.setContent("我变化了1");
		subject.setContent("我变化了2");

	}

}



输出结果:

观察者B 通过拉模式获得内容:我变化了1

观察者B 通过推模式获得内容:我变化了1

观察者A 通过拉模式获得内容:我变化了1

观察者A 通过推模式获得内容:我变化了1

观察者B 通过拉模式获得内容:我变化了2

观察者B 通过推模式获得内容:我变化了2

观察者A 通过拉模式获得内容:我变化了2

观察者A 通过推模式获得内容:我变化了2


此外,还可以在观察者observer中加入主题subject的引用,这样,在观察者需要取消注册subject时会更方便。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值