/**
* 模拟 观察者模式
* 场景:
* 小孩睡觉,家长工作
* 小孩醒来,家长喂饭
*/
public class ObserverDemo01 {
public static void main(String[] args) throws InterruptedException {
MyBaby b = new MyBaby();
MyParent p1 = new MyParent("爸爸");
MyParent p2 = new MyParent("妈妈");
MyParent p3 = new MyParent("姥姥");
MyParent p4 = new MyParent("奶奶");
b.addObserver(p1);
b.addObserver(p2);
b.addObserver(p3);
b.addObserver(p4);
for(int i=0;i<5;i++){
Thread.sleep(1000);
if(b.isAwake()){
b.sleep();
}else{
b.wakeUp();
}
}
}
}
/**
* 监听者
*/
interface IMyObserver{
void update(MyObservable obs);
}
/**
* 被监听者
*/
class MyObservable{
protected List<IMyObserver> list = new ArrayList<IMyObserver>();
public void addObserver(IMyObserver obs){
list.add(obs);
}
public void removeObserver(IMyObserver obs){
list.add(obs);
}
public void notifyAllObservers(){
for (IMyObserver obs : list) {
obs.update(this);
}
}
}
/**
* 以下为监听者、被监听者实例
*/
class MyBaby extends MyObservable{
private boolean isAwake = false;
public boolean isAwake(){
return this.isAwake;
}
public void wakeUp(){
System.out.println("baby醒了");
this.isAwake = true;
notifyAllObservers();
}
public void sleep(){
System.out.println("baby睡了");
this.isAwake = false;
notifyAllObservers();
}
}
class MyParent implements IMyObserver{
private String name;
public MyParent(String name){
this.name = name;
}
@Override
public void update(MyObservable obs) {
if( ((MyBaby)obs).isAwake() ){
System.out.println("["+name+"]来喂饭");
}else{
System.out.println("["+name+"]去工作");
}
}
}
运行结果:
baby醒了
[爸爸]来喂饭
[妈妈]来喂饭
[姥姥]来喂饭
[奶奶]来喂饭
baby睡了
[爸爸]去工作
[妈妈]去工作
[姥姥]去工作
[奶奶]去工作
baby醒了
[爸爸]来喂饭
[妈妈]来喂饭
[姥姥]来喂饭
[奶奶]来喂饭
baby睡了
[爸爸]去工作
[妈妈]去工作
[姥姥]去工作
[奶奶]去工作
baby醒了
[爸爸]来喂饭
[妈妈]来喂饭
[姥姥]来喂饭
[奶奶]来喂饭
/**
* 观察者模式(JDK提供了相应的工具类)
*
* 1、创建被观察者(baby)继承 java.util.Observable
* 在需要观察的动作(方法)完成后调用setChanged()方法和notifyObservers()方法通知观察者
* 2、创建观察者(parent)继承 java.util.Observer 重写 update() 方法
* 3、创建双方实例并将 观察者 注册到 被观察者 中(addObserver()方法)
*
* 实现观察/广播效果,避免了使用线程实现带来的大量开销
* 观察者/被观察者之间的关系也容易维护
*
* 注意:
* 1、观察者实例销毁前要通过deleteObserver()方法从监听列表中删除掉
* 否则对象之间依然会保持引用关系 对象未销毁 广播依然有效
* 2、避免循环依赖(死循环)
* 3、多线程下要小心
*
* 应用场景:
* 网络编程、AWT、Android
*/
public class ObserverDemo02 {
public static void main(String[] args) throws InterruptedException {
Baby b = new Baby();
Parent p1 = new Parent("爸爸");
Parent p2 = new Parent("妈妈");
Parent p3 = new Parent("姥姥");
Parent p4 = new Parent("奶奶");
b.addObserver(p1);
b.addObserver(p2);
b.addObserver(p3);
b.addObserver(p4);
for(int i=0;i<5;i++){
Thread.sleep(1000);
if(b.isAwake()){
b.sleep();
}else{
b.wakeUp();
}
}
}
}
class Baby extends Observable{
private boolean isAwake = false;
public boolean isAwake(){
return this.isAwake;
}
public void wakeUp(){
System.out.println("baby醒了");
this.isAwake = true;
setChanged();
notifyObservers();
}
public void sleep(){
System.out.println("baby睡了");
this.isAwake = false;
setChanged();
notifyObservers();
}
}
class Parent implements Observer{
private String name;
public Parent(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if( ((Baby)o).isAwake() ){
System.out.println("["+name+"]来喂饭");
}else{
System.out.println("["+name+"]去工作");
}
}
}
运行结果(同上):
baby醒了
[奶奶]来喂饭
[姥姥]来喂饭
[妈妈]来喂饭
[爸爸]来喂饭
baby睡了
[奶奶]去工作
[姥姥]去工作
[妈妈]去工作
[爸爸]去工作
baby醒了
[奶奶]来喂饭
[姥姥]来喂饭
[妈妈]来喂饭
[爸爸]来喂饭
baby睡了
[奶奶]去工作
[姥姥]去工作
[妈妈]去工作
[爸爸]去工作
baby醒了
[奶奶]来喂饭
[姥姥]来喂饭
[妈妈]来喂饭
[爸爸]来喂饭
/**
* 妈妈,他拿咱裤子了
* 谁呀
* 逗你玩
*/
public class ObserverDemo03 {
public static void main(String[] args) throws InterruptedException {
String[] arr = {"褂子","裤子","褥单子"};
YiJia yijia = new YiJia(arr);
XiaoTou dnw = new XiaoTou("逗你玩",yijia);
XiaoHu hu = new XiaoHu();
yijia.addObserver(hu);
for(int i=0;i<arr.length;i++){
dnw.tou();
Thread.sleep(1000);
}
}
}
/**
* 晾衣架
*/
class YiJia extends Observable{
private int initSize;
private String[] arr;
public YiJia(String[] arr){
this.arr = arr;
this.initSize = arr.length;
}
public int getInitSize(){
return initSize;
}
public void get(XiaoTou xt){
int index = arr.length-1;
String oldVal = arr[index];
System.out.println("====["+xt.name+"]拿走了["+oldVal+"]");
xt.hold = oldVal;
String[] newArr = new String[index];
System.arraycopy(arr, 0, newArr, 0, index);
arr = newArr;
setChanged();
notifyObservers(xt);
}
}
/**
* 小偷(逗你玩)
*/
class XiaoTou{
private YiJia yijia;
String name;
String hold;
public XiaoTou(String name, YiJia yijia){
this.name = name;
this.yijia = yijia;
}
public void tou(){
yijia.get(this);
}
}
/**
* 小虎
*/
class XiaoHu implements Observer{
@Override
public void update(Observable o, Object arg) {
if(arg instanceof XiaoTou){
System.out.println("妈妈,他那咱*"+((XiaoTou)arg).hold+"*了!");
System.out.println("谁呀?");
System.out.println(((XiaoTou)arg).name);
}
}
}
运行结果:
====[逗你玩]拿走了[褥单子]
妈妈,他那咱*褥单子*了!
谁呀?
逗你玩
====[逗你玩]拿走了[裤子]
妈妈,他那咱*裤子*了!
谁呀?
逗你玩
====[逗你玩]拿走了[褂子]
妈妈,他那咱*褂子*了!
谁呀?
逗你玩