Observer(观察者)模式是比较常用的一个模式,他让主题和观察者之间松耦合
定义:定义对象间一对多的依赖,这样一来,当一个对象发生改变,其他依赖者会得到通知并自动更新.
作为观察者,主题只知道他实现一个接口Oberver,主题不需要知道他具体是谁,需要实现什么操作.
任何时候我们都可以增加新的观察者.因为主题实现的是一个实现oberver的抽象接口列表,所以我们可以随时增加和删除观察者
主题不用了解其他的,只需要给现有注册的观察者发消息就可以了,观察者的增加和改变,不需要修改主题的代码.
主题和观察者,我们可以重复使用,改变一方不会影响另外一方,说到底就是为了达到解耦合的目的.
应用场合:
新京报,他是一个主题,很多人都可以定购他,他不需要了解你订购他是干吗,他只知道你付了钱,他给你一份报纸,到什么地址.如果他修改版面,他会通知你,比如说,最近物价上涨.可能需要上涨几毛钱.(有更改就会通知依赖者)
而订购他的人或者公司,属于观察者也就是依赖者,只有2个参数,一个是注册,一个是解除注册.注册后,就会收到报纸的最新消息,一有修改就会通知你.解除注册后,你还是你,但是你已经不属于依赖者了,就不会接到相应的消息.你可以今天注册,今天解除(这是你的事情).不会影响到其他的东西,也就是松耦合.
首先我们来模拟JDK里面有自带的类实现观察者模式:
实现一个电脑厂商和地区代理的示例,一对多关系依赖
GeneralProxy.java
package com.linpyi.computer;
/**
* 电脑总代理接口
* @author work
*
*/
public interface GeneralProxy {
/**
* 注册电脑代理
* @param o
*/
public void registerComputerProxy(Observer o);
/**
* 移除电脑代理
* @param o
*/
public void removeComputerProxy(Observer o);
/**
* 更新代理价格
*/
public void notifyComputerProxy();
}
Observer.java
package com.linpyi.computer;
/**
* 电脑观察者,自己写的代理接口
* @author work
*
*/
public interface Observer {
/**
* 更新电脑信息
* @param name 电脑品牌
* @param price 电脑价格
* @param info 电脑描述
*/
public void update(String name,float price,String info);
}
BranchProxy.java
package com.linpyi.computer;
/**
* 电脑分代理接口
* @author work
*
*/
public interface BranchProxy {
/**
* 默认方法
*/
public void display();
}
LenvoComputer.java
package com.linpyi.computer;
import java.util.ArrayList;
/**
* lenovo电脑
* @author work
*
*/
public class LenvoComputer implements GeneralProxy {
private ArrayList proxys ;
private String name;
private float price;
private String info;
public LenvoComputer(){
proxys = new ArrayList();
}
/**
* 更改lenvo分代理的信息
*/
public void notifyComputerProxy() {
for(int i = 0 ;i<proxys.size();i++){
Observer proxy = (Observer)proxys.get(i);
proxy.update(name, price, info);
}
}
/**
* 设置lenvo的电脑价格和信息
* @param name 电脑名称
* @param price 电脑价格
* @param info 电脑描述信息
*/
public void setLenvo(String name,float price,String info){
this.name=name;
this.price=price;
this.info=info;
notifyComputerProxy();
}
/**
* 注册lenvo代理
*/
public void registerComputerProxy(Observer o) {
proxys.add(o);
}
/**
* 移除lenvo代理
*/
public void removeComputerProxy(Observer o) {
// TODO Auto-generated method stub
int i = proxys.indexOf(o);
if(i>=0){
proxys.remove(o);
}
}
}
ChinaProxy.java
package com.linpyi.computer;
/**
* 中国地区代理类,使用自己写的代理接口
* @author
*
*/
public class ChinaProxy implements BranchProxy, Observer {
private GeneralProxy generalProxy;
private String name ;
private float price;
private String info;
public ChinaProxy(GeneralProxy generalProxy){
this.generalProxy=generalProxy;
generalProxy.registerComputerProxy(this);//注册代理
}
/**
* 默认方法
*/
public void display() {
// TODO Auto-generated method stub
System.out.println("中国代理");
System.out.println("型号"+name);
System.out.println("价格"+price);
System.out.println("描述信息"+info);
}
/**
* 更新方法
*/
public void update(String name, float price, String info) {
// TODO Auto-generated method stub
this.name=name;
this.price=price;
this.info=info;
display();
}
}
JapanProxy.java
package com.linpyi.computer;
/**
* 日本代理,使用自己写的代理接口
*
* @author work
*
*/
public class JapanProxy implements BranchProxy, Observer {
private String name;
private String info;
private float price;
private GeneralProxy generalProxy;
public JapanProxy(GeneralProxy generalProxy) {
this.generalProxy = generalProxy;
generalProxy.registerComputerProxy(this);
}
public void update(String name, float price, String info) {
this.name = name;
this.price = price;
this.info = info;
display();
}
public void display() {
// TODO Auto-generated method stub
System.out.println("日本代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
Client.java
package com.linpyi.computer;
public class Client {
public static void main(String[] args){
//使用自己写的观察模式方法
LenvoComputer lenvo = new LenvoComputer();
ChinaProxy chinaProxy = new ChinaProxy(lenvo);
JapanProxy japanProxy = new JapanProxy(lenvo);
lenvo.setLenvo("lenvo0001", 8000, "disk 160G , memory 2G");
}
}
使用JDK里面有自带的类实现观察者模式:
HpComputer.java
package com.linpyi.computer;
import java.util.Observable;
/**
* HP电脑代理,使用的是JDK自带的观察者模式类(Observable)
* @author work
*
*/
public class HpComputer extends Observable {
private String name;
private float price;
private String info;
public void measurementsChanged(){
setChanged();//观察者类里的方法,主要用于开关
notifyObservers();//继承类里的方法(通知观察者)
}
public void setMeasurements(String name,float price,String info){
this.name=name;
this.price=price;
this.info=info;
measurementsChanged();
}
public String getName(){
return name;
}
public float getPrice(){
return price;
}
public String getInfo(){
return info;
}
}
IndiaProxy.java
package com.linpyi.computer;
import java.util.Observable;
import java.util.Observer;
/**
* 印度电脑代理(使用JDK自带的接口)
* @author work
*
*/
public class IndiaProxy implements Observer, BranchProxy {
private Observable observable;
private String name;
private String info;
private float price;
public IndiaProxy(Observable observable) {
this.observable = observable;
observable.addObserver(this);//增加观察者(JDK自带的)
}
/**
* 更新方法,使用的是JDK自带的方法
*/
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof HpComputer) {
HpComputer computer = (HpComputer) o;
this.name = computer.getName();
this.price = computer.getPrice();
this.info = computer.getInfo();
display();
}
}
public void display() {
// TODO Auto-generated method stub
System.out.println("印度代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
KoreaProxy.java
package com.linpyi.computer;
import java.util.Observable;
import java.util.Observer;
/**
* 韩国代理,使用的是JDK自带的接口(Observer)
* @author work
*
*/
public class KoreaProxy implements Observer, BranchProxy {
private Observable observable;
private String name;
private String info;
private float price;
public KoreaProxy(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof HpComputer) {
HpComputer computer = (HpComputer) o;
this.name = computer.getName();
this.price = computer.getPrice();
this.info = computer.getInfo();
display();
}
}
public void display() {
// TODO Auto-generated method stub
System.out.println("韩国代理");
System.out.println("型号" + name);
System.out.println("价格" + price);
System.out.println("描述信息" + info);
}
}
Client.java
package com.linpyi.computer;
public class Client {
public static void main(String[] args){
//使用JDK的观察模式方法
HpComputer hp = new HpComputer();
KoreaProxy koreaProxy = new KoreaProxy(hp);
IndiaProxy IndiaProxy = new IndiaProxy(hp);
hp.setMeasurements("hp0001", 7000, "disk 250G , memory 10G");
}
}
JDK里面有自带的类实现观察者模式,在java.util.Observable,注意这是类而不是接口,类有类的局限性,因为JAVA只能继承