Observer模式

作者: 吃啥呀 | 来源:发表于2018-07-16 15:21 被阅读117次

    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

    相关文章

      网友评论

        本文标题:Observer模式

        本文链接:https://www.haomeiwen.com/subject/npumpftx.html