观察者模式

一、观察者模式

观察者的通俗理解可以参考订阅发布的方式,每一个订阅内容,一旦被观察对象内容改变就会向观察者发送消息,告诉观察者修改了内容或者是观察者获取最新内容
在这里插入图片描述

  • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,Subject已经通过方法已经定义好了业务逻辑。抽象主题所要做的就是实现attach()添加观察者,detach()删除观察者,notify()向观察者发送消息(调用update)
  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。主要是将notify()的封装
  • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。主要定义update方法,可以定义为接受具体信息(通过被观察者推送消息的模式),或者接受被观察者的引用(通过观察者拉取消息的模式)
  • ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

二、订阅/发布模式(push模式)

观察者 接受的是主题的数据

1、抽象观察者

public interface IObserver {
	public void update(String message);

}

2、具体观察者

public class Observer implements IObserver{
	private String name;
	//不同的观察者,订阅者不同
	public Observer(String name) {
		this.name = name;
	}

	@Override
	public void update(String message) {
		System.out.println(this.name+"接受消息:"+message);
		
	}

}

3、抽象主题

import java.util.ArrayList;
import java.util.List;

abstract class Subject {
	List<IObserver> list = new ArrayList<IObserver>();
	public void attach(IObserver observer) {
		list.add(observer);
	}
	public void detach(IObserver observer) {
		list.remove(observer);
	}
	public void notify(String message) {
		for(IObserver observer:list) {
			observer.update(message);
		}
	}
}

4、具体主题

public class ConcreteSub extends Subject{
	//notify方法的封装
	public void notifyConcrete(String message) {
		notify(message);
	}
}

5、test测试

public class Test {
	public static void main(String[] args) {
		ConcreteSub concrete = new ConcreteSub();
		Observer observer1 = new Observer("robin");
		Observer observer2 = new Observer("xiaoluo");
		Observer observer3 = new Observer("罗大");
		concrete.attach(observer1);
		concrete.attach(observer2);
		//不关联observer3,此时无法接受发布的消息
		concrete.notify("欢迎订阅");
	}

}

robin接受消息:欢迎订阅
xiaoluo接受消息:欢迎订阅

三、pop模式拉取模式

观察者 接受的是主题的引用
1、抽象观察者

public interface IObserver {
	public void update(Subject sub);

}

2、具体观察者

public class Observer implements IObserver{
	private String name;
	//不同的观察者,订阅者不同
	public Observer(String name) {
		this.name = name;
	}
	@Override
	//接受引用
	public void update(Subject sub) {
		String message = ((ConcreteSub)sub).getState();
		System.out.println(name+"自动拉取数据:"+message);
		
	}
}

3、抽象主题

import java.util.ArrayList;
import java.util.List;

abstract class Subject {
	List<IObserver> list = new ArrayList<IObserver>();
	public void attach(IObserver observer) {
		list.add(observer);
	}
	public void detach(IObserver observer) {
		list.remove(observer);
	}
	public void notifyOther() {
		for(IObserver observer:list) {
			observer.update(this);//传入自身引用
		}
	}
}

4、具体主题

public class ConcreteSub extends Subject{
	private String state;
	
	
	public String getState() {
		return state;
	}
	public void notifyConcrete(String message) {
		this.state = message;
		this.notifyOther();
	}
}

5、test测试

public class Test {
	public static void main(String[] args) {
		ConcreteSub concrete = new ConcreteSub();
		Observer observer1 = new Observer("robin");
		Observer observer2 = new Observer("xiaoluo");
		Observer observer3 = new Observer("罗大");
		concrete.attach(observer1);
		concrete.attach(observer2);
		concrete.attach(observer3);
		concrete.notifyConcrete("更新数据");
	}

}
robin自动拉取数据:更新数据
xiaoluo自动拉取数据:更新数据
罗大自动拉取数据:更新数据

四、标准模式(继承现有接口和抽象类)

1、Observal抽象类

(1)拉取,不传输任何数据

 public void notifyObservers() {
        notifyObservers(null);
    }

(2)推送,传输参数

public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
         
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);//调用update
    }

2、具体观察者

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

public class ObserverConcrete implements Observer {
	private String name;
	//不同的观察者,订阅者不同
	public ObserverConcrete(String name) {
		this.name = name;
	}
	@Override
	public void update(Observable o, Object arg) {
		String messageString = ((ConcreteSub)o).getState();
		System.out.println(name+"标准接口拉取数据:"+messageString);
		
	}

}

2、具体主题

import java.util.Observable;

public class ConcreteSub extends Observable{
	private String state;
	public String getState() {
		return state;
	}
	public void notifystand(String message) {
		this.state = message;
		this.setChanged();//设置状态已经改变
		this.notifyObservers();//内部调用Observer的update,此时选择的是拉取方式实现,当然可以选择推送方式
	}
}

5、test测试

public class Test {
	public static void main(String[] args) {
		ConcreteSub cocreSub = new ConcreteSub();
		ObserverConcrete o1 = new ObserverConcrete("罗大");
		ObserverConcrete o2 = new ObserverConcrete("罗二");
		ObserverConcrete o3 = new ObserverConcrete("罗三");
		cocreSub.addObserver(o1);
		cocreSub.addObserver(o2);
		cocreSub.addObserver(o3);
		cocreSub.notifystand("标准方式推送的数据");
	}

}

罗三标准接口拉取数据:标准方式推送的数据
罗二标准接口拉取数据:标准方式推送的数据
罗大标准接口拉取数据:标准方式推送的数据

五、引用

【1】demo参照:https://blog.csdn.net/yanbober/article/details/45484749

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值