Observer模式

java的设计模式


作用 当观察对象的状态发生变化时,通知给观察者(观察者订阅被观察者的状态)
应用 需要根据对象状态进行相应处理的场景

Observer.png

创建Subject类

package com.company;

import javax.swing.text.html.HTMLDocument;
import java.util.ArrayList;
import java.util.Iterator;

public abstract class Subject{

    private ArrayList observers = new ArrayList();//保存Observer们
    public void addObserver(Observer observer){
        observers.add(observer);
    };//注册Obeserver
    public void notifyObservers(){
        //向Observer发送通知
        Iterator it = observers.iterator();
        while (it.hasNext()){
            Observer observer = (Observer)it.next();
            observer.update();
        }
    }
    public abstract int getState();
    public abstract void setState();\\写成抽象方法,便于拓展
}

Subject的子类

package com.company;

import java.util.Random;

public class Subjecta extends Subject{
    private int number;
    private Random random = new Random();

    @Override
    public int getState() {
        return number;
    }

    @Override
    public void setState() {
        for(int i = 0 ;i < 10 ;i++){
            number = random.nextInt(48);
            notifyObservers();
        }
    }
}

创建抽象Observer类

package com.company;

public abstract class Observer {
    protected Subject subject;\\有Subject类的实例化对象,便于获取被观察者的信息
    public abstract void update();\\在子类中实现更新的具体操作
}

创建实体观察类

package com.company;

public class Observera extends Observer{
    public Observera(Subject subject){
        this.subject = subject;
        this.subject.addObserver(this);
    }

    @Override
    public void update() {
        System.out.println( "Observera : " + subject.getState());
    }
}

public class Observerb extends Observer{
    public Observerb(Subject subject){
        this.subject = subject;
        this.subject.addObserver(this);
    }

    @Override
    public void update() {
        System.out.print("Observerb : ");
        for(int i = 0 ;i< subject.getState();i++) {
            System.out.print('-');
        }
        System.out.println();
    }
}

在客户端(Main)使用

package com.company;

public class Main {

    public static void main(String[] args) {
        Subject subject = new Subjecta();
        new Observera(subject);
        new Observerb(subject);\\创建观察者

        subject.setState();\\设置状态(改变状态)
    }
}

另一种实现方法

  • 抽象Observer类变为为接口——ObserverI
  • Subject的实例化对象subject变成接口ObserverI的update()方法的参数(原来是抽象类Observer的私有成员)
package com.company;

public interface ObserverI {
    public abstract void update(Subject subject);
}
  • Observer类由抽象类变成了接口,Subject类中添加观察者的方法和向Observer发送通知的方法也应当重写
public abstract class Subject{

    private ArrayList observers = new ArrayList();//保存Observer们
    public void addObserver(Observer observer){
        observers.add(observer);
    };//第一种,注册obeserver

    public void addObserver(ObserverI observer){
        observers.add(observer);
    };//第二种方法,注册Obeserver的方式

    public void notifyObservers(){
        //向Observer发送通知
        Iterator it = observers.iterator();
        while (it.hasNext()){
            Observer observer = (Observer)it.next();
            observer.update();
        }
    }//第一种

    public void notifyObservers2(){
        //向Observer发送通知
        Iterator it = observers.iterator();
        while (it.hasNext()){
            ObserverI observer = (ObserverI)it.next();
            observer.update(this);//改变后的update方法需要传入一个subject进去
        }
    }//第二种方法
//注意:在状态改变后(setState)应当调用的发送通知的方法也应当换成第二种对应的
}

  • 继承ObserverI接口,实现具体方法
package com.company;

public class ObserverI1 implements ObserverI{
    @Override
    public void update(Subject subject) {
        System.out.println( "Observera : " + subject.getState());
    }
}

public class ObserverI2 implements ObserverI{
    @Override
    public void update(Subject subject) {
        System.out.print("Observerb : ");
        for(int i = 0 ;i< subject.getState();i++) {
            System.out.print('-');
        }
        System.out.println();
    }
}

  • 由于ObserverI接口只有抽象方法,在Observer的具体实现类中没有Subject类的实例化对象作为类成员,无法在构造函数中直接添加observer(注册observer),需要在客户端(Main)添加
//第一种注册observer的方式
public class Observerb extends Observer{
    public Observerb(Subject subject){
        this.subject = subject;
        this.subject.addObserver(this);//改变后
    }
}//第一种只要创建了Subject具体实现类的实例化对象,就在被观察者中添加了观察者,

//第二种方法,注册Observer的方式
public class Main {

    public static void main(String[] args) {
        Subject subject = new Subjecta();
        Observer observer1 = new Observera();
        Observer observer2 = new Observerb();//创建观察者
            subject.addObserver(observer1);
            subject.addObserver(observer2);
        subject.setState();\\设置状态(改变状态)
    }
}//现在,创建观察者后,还需调用被观察者中添加观察者的方法)

注意点

Observer的顺序

Subject角色中有多个Observer角色,在示例代码中是先注册的Observer的update方法先被调用

Observer的行为对Subject的影响

Subject的状态变化 ---> 通知Observer ---> Observer调用Subject的方法 ---> 导致Subject的状态发生变化 ---> 通知Observer
导致方法被循环调用

update方法传入的参数

void update(Subject subject); 
void update(int number);  
void update(Subject subject,int number); 

可以传入Subject实例对象,也可以传入该实例中的某些数据,第一种更加灵活

拓展
java.utill.Observer 接口
java.utill.Observable 类 ——被观察的Subject角色

 public void update(Observable obj,Object arg)//Object类的实例是附加信息

缺陷Subject角色必须是java.utill.Observable 类的子类,但是java是单一继承

以上完整的代码上传到了github仓库
https://github.com/chenshuyuhhh/DesignPatternDemo.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 参考资料:菜鸟教程之设计模式 设计模式概述 设计模式(Design pattern)代表了最佳的实践,通常被有经验...
    Steven1997阅读 1,208评论 1 12
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,806评论 18 399
  • 1. 想起读这本书的源头是一部网络剧---《灵魂摆渡》,当初是冲着赵吏这个角色的扮演者于毅才开始看剧,我想每个人心...
    苏苏书书阅读 318评论 0 3
  • I:重述 WHAT: 这个片段讲述的是如何运用减压三步法得到全面的放松和休息。 WHY: 现在生活工作节奏不断加快...
    假装Yes阅读 160评论 0 0
  • 亲子日记第125篇 中午看到牛老师在家长群里发的她已经执教完成,现在已经在回家的路上了,我眼睛不知不觉就湿...
    一年级七班王烁桦妈妈阅读 165评论 0 1