观察者模式

1.观察者模式的定义:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

2.举例分析:

定义的理解总是需要实例来解析的,下面就以微信服务号为背景,介绍观察者模式。

如上图所示,服务号就是主题,使用者就是观察者。现在要明确下功能:

1)服务号就是主题,业务就是推送消息

2)观察者只需要订阅主题,只要有新的消息就会送来

3)当不想要此主题消息时,取消订阅

4)只要服务号还在,就会一直有人订阅

现在来看看观察者模式的类图:

 

 3.代码:

首先开始写主题接口,和观察者接口:

package com.zhy.pattern.observer;

/**
* 主题接口,所有的主题必须实现此接口
*
* @author zhy
*
*/
public interface Subject
{
/**
* 注册一个观察着
*
* @param observer
*/
public void registerObserver(Observer observer);

/**
* 移除一个观察者
*
* @param observer
*/
public void removeObserver(Observer observer);

/**
* 通知所有的观察着
*/
public void notifyObservers();

}

package com.zhy.pattern.observer;

/**
* @author zhy 所有的观察者需要实现此接口
*/
public interface Observer
{
public void update(String msg);

}

 

接下来3D服务号的实现类:
package com.zhy.pattern.observer;

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

public class ObjectFor3D implements Subject
{
private List<Observer> observers = new ArrayList<Observer>();
/**
* 3D彩票的号码
*/
private String msg;

@Override
public void registerObserver(Observer observer)
{
observers.add(observer);
}

@Override
public void removeObserver(Observer observer)
{
int index = observers.indexOf(observer);
if (index >= 0)
{
observers.remove(index);
}
}

@Override
public void notifyObservers()
{
for (Observer observer : observers)
{
observer.update(msg);
}
}

/**
* 主题更新消息
*
* @param msg
*/
public void setMsg(String msg)
{
this.msg = msg;

notifyObservers();
}

}

模拟两个使用者:
package com.zhy.pattern.observer;

public class Observer1 implements Observer
{

private Subject subject;

public Observer1(Subject subject)
{
this.subject = subject;
subject.registerObserver(this);
}

@Override
public void update(String msg)
{
System.out.println("observer1 得到 3D 号码 -->" + msg + ", 我要记下来。");
}

}

package com.zhy.pattern.observer;

public class Observer2 implements Observer
{
private Subject subject ;

public Observer2(Subject subject)
{
this.subject = subject ;
subject.registerObserver(this);
}

@Override
public void update(String msg)
{
System.out.println("observer2 得到 3D 号码 -->" + msg + "我要告诉舍友们。");
}



}
可以看出:服务号中维护了所有向它订阅消息的使用者,当服务号有新消息时,通知所有的使用者。整个架构是一种松耦合,主题的实现不依赖与使用者,当增加新的使用者时,主题的代码不需要改变;使用者如何处理得到的数据与主题无关;
最后看下测试代码:

package com.zhy.pattern.observer.test;

import com.zhy.pattern.observer.ObjectFor3D;
import com.zhy.pattern.observer.Observer;
import com.zhy.pattern.observer.Observer1;
import com.zhy.pattern.observer.Observer2;
import com.zhy.pattern.observer.Subject;

public class Test
{
public static void main(String[] args)
{
//模拟一个3D的服务号
ObjectFor3D subjectFor3d = new ObjectFor3D();
//客户1
Observer observer1 = new Observer1(subjectFor3d);
Observer observer2 = new Observer2(subjectFor3d);

subjectFor3d.setMsg("20140420的3D号码是:127" );
subjectFor3d.setMsg("20140421的3D号码是:333" );

}
}

输出结果:
observer1 得到 3D 号码 -->20140420的3D号码是:127, 我要记下来。
observer2 得到 3D 号码 -->20140420的3D号码是:127我要告诉舍友们。
observer1 得到 3D 号码 -->20140421的3D号码是:333, 我要记下来。
observer2 得到 3D 号码 -->20140421的3D号码是:333我要告诉舍友们。

对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。

 

4.Java内置的类实现观察者模式: 

首先是一个3D彩票服务号主题:

package com.zhy.pattern.observer.java;

import java.util.Observable;

public class SubjectFor3d extends Observable
{
private String msg ;


public String getMsg()
{
return msg;
}


/**
* 主题更新消息
*
* @param msg
*/
public void setMsg(String msg)
{
this.msg = msg ;
setChanged();
notifyObservers();
}
}
下面是一个双色球的服务号主题:
package com.zhy.pattern.observer.java;

import java.util.Observable;

public class SubjectForSSQ extends Observable
{
private String msg ;


public String getMsg()
{
return msg;
}


/**
* 主题更新消息
*
* @param msg
*/
public void setMsg(String msg)
{
this.msg = msg ;
setChanged();
notifyObservers();
}
}

最后是我们的使用者:
package com.zhy.pattern.observer.java;

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

public class Observer1 implements Observer
{

public void registerSubject(Observable observable)
{
observable.addObserver(this);
}

@Override
public void update(Observable o, Object arg)
{
if (o instanceof SubjectFor3d)
{
SubjectFor3d subjectFor3d = (SubjectFor3d) o;
System.out.println("subjectFor3d's msg -- >" + subjectFor3d.getMsg());
}

if (o instanceof SubjectForSSQ)
{
SubjectForSSQ subjectForSSQ = (SubjectForSSQ) o;
System.out.println("subjectForSSQ's msg -- >" + subjectForSSQ.getMsg());
}
}
}
看一个测试代码:
package com.zhy.pattern.observer.java;

public class Test
{
public static void main(String[] args)
{
SubjectFor3d subjectFor3d = new SubjectFor3d() ;
SubjectForSSQ subjectForSSQ = new SubjectForSSQ() ;

Observer1 observer1 = new Observer1();
observer1.registerSubject(subjectFor3d);
observer1.registerSubject(subjectForSSQ);


subjectFor3d.setMsg("hello 3d'nums : 110 ");
subjectForSSQ.setMsg("ssq'nums : 12,13,31,5,4,3 15");

}
}

测试结果:
subjectFor3d's msg -- >hello 3d'nums : 110
subjectForSSQ's msg -- >ssq'nums : 12,13,31,5,4,3 15

可以看出,使用Java内置的类实现观察者模式,代码非常简洁,addObserver,removeObserver,notifyObservers都已经实现了,所有可以看出Observable(主题)是一个类,而不是一个接口,基本上书上都对于Java的如此设计抱有反面的态度,觉得Java内置的观察者模式,违法了面向接口编程这个原则,但是如果转念想一想,的确你拿一个主题在这写观察者模式(我们自己的实现),接口的思想很好,但是如果现在继续添加很多个主题,每个主题的ddObserver,removeObserver,notifyObservers代码基本都是相同的,接口是无法实现代码复用的,而且也没有办法使用组合的模式实现这三个方法的复用,所以把这三个方法在类中实现是合理的。

https://github.com/youlookwhat/DesignPattern

转载于:https://www.cnblogs.com/GaoHanyuan/p/9839569.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值