设计模式之观察者模式

❤角色组成

❤抽象目标(Subject):增加观察者方法+删除观察者方法+通知所有观察者的方法。一般用一个抽象类和接口来实现。

❤抽象观察者(Observer):有一个更新方法,在得到主题通知时更新自己。(即把目标信息同步给自己)

❤具体目标(ConcreteSubject):目标信息+观察者集合。是一个具体的信息,信息状态改变后通知所有观察者(比如天气状态)

❤具体观察者(ConcreteObserver):目标信息+自己的名字+自己的工作。更新得到目标信息后通知自己可以做自己的事情了。(比如天气晴朗+A+逛街)

1.手动实现

❤抽象目标

public interface Subject {
	// 添加观察者
	public void add(Observer observer);
	// 删除观察者
	public void delete(Observer observer);
	// 通知所有观察者
	public void notifyObservers();
}

❤抽象观察者

public interface Observer {
	// 更新目标信息
	// 1.推模型,由目标推送给观察者需要的信息,按需推送,这里观察者只需要天气信息
	public void update(String weatherState);
	// 2.拉模型,由观察者拉取目标的整个对象
	// public void update(Subject subject);
}

❤具体目标

public class ConcreteSubject implements Subject {
	private String weatherState;// 目标信息
	public List<Observer> observers = new ArrayList<Observer>();// 观察者集合

	public String getWeatherState() {
		return weatherState;
	}
	public void setWeatherState(String weatherState) {
		this.weatherState = weatherState;
		this.notifyObservers();
	}
	public void add(Observer observer) {
		observers.add(observer);
	}
	public void delete(Observer observer) {
		observers.remove(observer);
	}
	// 1.推模型
	public void notifyObservers() {
		for (Observer observer : observers) {
			observer.update(weatherState);// 即通过调用观察者的update方法,将目标信息更新给观察者
		}
	}
	// 2.拉模型
	// public void notifyObservers() {
	// for(Observer observer : observers){
	// observer.update(this);
	// }
	// }
}

❤具体观察者

public class ConcreteObserver implements Observer {
	private String name;// 观察者名字
	private String work;// 观察者想要做的事
	private String weatherState;// 天气状态

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getWeatherState() {
		return weatherState;
	}
	public void setWeatherState(String weatherState) {
		this.weatherState = weatherState;
	}
	public String getWork() {
		return work;
	}
	public void setWork(String work) {
		this.work = work;
	}
	// 1.推模型
	public void update(String weatherState) {
		System.out.println(name + "获得信息:" + weatherState + "  " + work);
	}
	// 2.拉模型
	// public void update(Subject subject) {
	// weatherState = ((ConcreteSubject)subject).getWeatherState();//强转为子类
	// System.out.println(name+"获得信息:"+weatherState+"  "+work);
	// }
}

❤测试类

public class Client {
	public static void main(String[] args) {
		// 1.创建目标
		ConcreteSubject subject = new ConcreteSubject();
		// 2.创建观察者
		ConcreteObserver observerA = new ConcreteObserver();
		observerA.setName("A");
		observerA.setWork("出去逛街");
		ConcreteObserver observerB = new ConcreteObserver();
		observerB.setName("B");
		observerB.setWork("出去打球");
		// 3.添加观察者
		subject.add(observerA);
		subject.add(observerB);
		// 4.目标发布信息
		subject.setWeatherState("天气晴朗");
	}
}

❤运行结果

A获得信息:天气晴朗  出去逛街

B获得信息:天气晴朗  出去打球


❤推模型和拉模型

推模型:目标主动向观察者推送目标的部分信息,按需推送。

拉模型:观察者主动到目标对象中获取信息,一般这种模型会把目标对象自身通过update方法传递给观察者,即拉取整个对象,复用性高。

 

2. 通过JDK自带的接口实现

❤具体目标(继承Obervervable类,不要在意名字)

import java.util.Observable;
public class ConcreteSubject extends Observable {
	private String weatherState;
	public String getWeatherState() {
		return weatherState;
	}
	public void setWeatherState(String weatherState) {
		this.weatherState = weatherState;
		this.setChanged();// 开启通知,必不可少	
		this.notifyObservers(weatherState);// 推模型
		this.notifyObservers();// 拉模型
	}
}

❤具体观察者(实现Observer接口)

import java.util.Observable;
import java.util.Observer;
public class ConcreteObserver implements Observer {
	private String name;
	private String work;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getWork() {
		return work;
	}
	public void setWork(String work) {
		this.work = work;
	}
	// 第一个参数是拉模型,第二个参数是推模型
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("推模型:" + name + "获得信息:" + arg + "  " + work);
		System.out.println("拉模型:" + name + "获得信息:"
				+ ((ConcreteSubject) o).getWeatherState() + "  " + work);
	}
}

❤测试类

public class Client {
	public static void main(String[] args) {
		// 1.创建目标
		ConcreteSubject subject = new ConcreteSubject();
		// 2.创建观察者
		ConcreteObserver observerA = new ConcreteObserver();
		observerA.setName("A");
		observerA.setWork("出去逛街");
		ConcreteObserver observerB = new ConcreteObserver();
		observerB.setName("B");
		observerB.setWork("出去打球");
		// 3.添加观察者
		subject.addObserver(observerA); // 自带的添加方法
		subject.addObserver(observerB);
		// 4.目标发布信息
		subject.setWeatherState("天气晴朗");
	}
}

❤运行结果

推模型:B获得信息:天气晴朗  出去打球

拉模型:B获得信息:天气晴朗  出去打球

推模型:A获得信息:天气晴朗  出去逛街

拉模型:A获得信息:天气晴朗  出去逛街

 

❤JDK自带对比和自己实现对比

1.JDK自带抽象目标和抽象观察者不需要我们去实现,比我们自己实现代码工作量少

2.通过自己实现的方式在notifyObservers方法遍历集合的过程中通过if判断分类通知,而JDK会通知所有观察者

3.JDK具体观察者中的update方法两个参数Observable o, Object arg即拉模型和推模型,两者都支持推拉模型

 

❤观察者模式的优点

        使目标和观察者之间解耦,原本目标改变需要依次去调用观察者通知,现在目标set新的状态自动通知,核心就是把通知观察者的方法(即update方法)放到了set方法中实现。







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值