观察者模式
对象为一对多关系时,当修改对象,要自动通知其依赖的对象,这个时候就可以使用观察者模式,观察者模式属于行为型模式。
例如双色球开奖,其开奖结果是发布在双色球官网,其开放了一个公共接口,我们可以通过这个接口拿到本期及往期的开奖数据,然后公布在自己的平台上,因此我们除了可以在双色球官网查看结果外,还可以在QQ、支付宝、TV等第三方平台上查看开奖结果。
首先,我们来看一下通常的做法,分析他的缺点。
public class QQMessageInformation{
private DoubleColorBallPublish doubleColorBallPublish;
public QQMessageInformation(DoubleColorBallPublish doubleColorBallPublish){
this.doubleColorBallPublish=doubleColorBallPublish;
}
public void send() {
System.out.println("QQ Show Double Color Ball "+this.doubleColorBallPublish.getPublishTimes()+" Times:"+this.doubleColorBallPublish.getNumber());
}
}
public class DoubleColorBallPublish {
private Integer publishTimes;
private String number;
private QQMessageInformation qqMessageInformation;
public DoubleColorBallPublish(QQMessageInformation qqMessageInformation){
this.qqMessageInformation=qqMessageInformation;
}
public Integer getPublishTimes() {
return publishTimes;
}
public String getNumber() {
return number;
}
public void setNumber(String number,Integer publishTimes) {
this.number = number;
this.publishTimes=publishTimes;
showInformations();
}
public void showInformations(){
qqMessageInformation.send();
}
}
DoubleColorBallPublish类是双色球官方发布开奖的一个类,其有发布时间和中奖号码两个属性,这里对QQ平台进行了接入,代码中聚合了QQMessageInformation类,在实例化DoubleColorBallPublish类的时候需要传入QQMessageInformation类,对该类进行管理。在setNumber方法中来设置此次中奖号码及当前发布时间,并同时调用showInformations()方法,通知第三方平台进行更新,showInformations()方法中为QQMessageInformation对象调用send()方法将信息通过自己平台推送出去。
假如现在阿里平台也要接入平台获取双色球开奖信息,此时我们看如下代码:
public class ApliPayInformation{
private DoubleColorBallPublish doubleColorBallPublish;
public ApliPayInformation(DoubleColorBallPublish doubleColorBallPublish){
this.doubleColorBallPublish=doubleColorBallPublish;
}
public void send() {
System.out.println("AppliPay Show Double Color Ball "+this.doubleColorBallPublish.getPublishTimes()+" Times:"+this.doubleColorBallPublish.getNumber());
}
}
public class DoubleColorBallPublish {
private Integer publishTimes;
private String number;
private QQMessageInformation qqMessageInformation;
private ApliPayInformation apliPayInformation;
public DoubleColorBallPublish(QQMessageInformation qqMessageInformation,ApliPayInformation apliPayInformation){
this.qqMessageInformation=qqMessageInformation;
this.apliPayInformation=apliPayInformation;
}
public Integer getPublishTimes() {
return publishTimes;
}
public String getNumber() {
return number;
}
public void setNumber(String number,Integer publishTimes) {
this.number = number;
this.publishTimes=publishTimes;
showInformations();
}
public void showInformations(){
qqMessageInformation.send();
apliPayInformation.send();
}
我们可以看到在DoubleColorBallPublish类中又聚合了ApliPayInformation类,在构造方法中需要传入ApliPayInformation对象,在showInformations()方法中加上对ApliPayInformation的通知。那么如果我们再接入微信平台、TV平台呢,是不是都要按此步骤去添加,这样每加一个平台就要去修改代码,而且构造方法处还会变得越来越臃肿,显然,这不是一个很好的方式,那么,如何来修改呢,我们就借用观察者模式来改造我们的代码。
现在我们的结构设计如上图所示,具体代码如下
public abstract class Information {
protected DoubleColorBallPublish doubleColorBallPublish;
public abstract void send();
}
public class QQMessageInformation extends Information{
public QQMessageInformation(DoubleColorBallPublish doubleColorBallPublish){
this.doubleColorBallPublish=doubleColorBallPublish;
this.doubleColorBallPublish.pushInformation(this);
}
@Override
public void send() {
System.out.println("QQ Show Double Color Ball "+this.doubleColorBallPublish.getPublishTimes()+" Times:"+this.doubleColorBallPublish.getNumber());
}
}
public class ApliPayInformation extends Information {
public ApliPayInformation(DoubleColorBallPublish doubleColorBallPublish){
this.doubleColorBallPublish=doubleColorBallPublish;
this.doubleColorBallPublish.pushInformation(this);
}
@Override
public void send() {
System.out.println("AppliPay Show Double Color Ball "+this.doubleColorBallPublish.getPublishTimes()+" Times:"+this.doubleColorBallPublish.getNumber());
}
}
public class TVInformation extends Information {
public TVInformation(DoubleColorBallPublish doubleColorBallPublish){
this.doubleColorBallPublish=doubleColorBallPublish;
this.doubleColorBallPublish.pushInformation(this);
}
@Override
public void send() {
System.out.println("TV Show Double Color Ball "+this.doubleColorBallPublish.getPublishTimes()+" Times:"+this.doubleColorBallPublish.getNumber());
}
}
public class DoubleColorBallPublish {
private Integer publishTimes;
private String number;
private List<Information>informations=new ArrayList<Information>();
public Integer getPublishTimes() {
return publishTimes;
}
public String getNumber() {
return number;
}
public void setNumber(String number,Integer publishTimes) {
this.number = number;
this.publishTimes=publishTimes;
showInformations();
}
public void pushInformation(Information information){
informations.add(information);
}
public void showInformations(){
for (Information information:informations) {
information.send();
}
}
}
测试方法
public class KaiJiang {
public static void main(String[] args) {
DoubleColorBallPublish doubleColorBallPublish=new DoubleColorBallPublish();
new TVInformation(doubleColorBallPublish);
new QQMessageInformation(doubleColorBallPublish);
new ApliPayInformation(doubleColorBallPublish);
System.out.println("上一期开奖结果:");
doubleColorBallPublish.setNumber("01 03 06 13 27 31 : 04 13",20170814);
System.out.println("本期开奖结果:");
doubleColorBallPublish.setNumber("02 03 09 15 24 30 : 02 19",20170817);
}
}
测试结果
简单说一下代码,这里抽象了一个Information父类,各个平台继承该类并重写自己的推送方法。DoubleColorBallPublish类中增加了List<Information>属性,用来管理注册到这里的各个平台。在setNumber()方法赋值的时候来发布信息,在showInformations()方法中依次遍历对所有注册到双色球中心的平台进行通知发布信息。各个平台实例中,创建对象时需要指定双色球服务中心,并调用双色球中心的注册方法将自己注册进去,在send()方法中用来推送最新的双色球服务中心的数据。
以上就是对观察者模式的介绍,本次介绍了观察者模式的使用场景及如何实现一个观察者模式。