设计模式-Observer模式(观察者模式)

观察者模式

也称为发布-订阅模式。Observer模式适用于根据对象状态进行相应处理的场景。

示例程序

观察者将观察一个会生成数值的对象,并将它生成的数值结果显示出来。不过,不同的观察者的显示方式不一样。DigitObserver会以数字的形式显示数值,而GraphObserver则会以“*”的形式显示数值。

观察者接口 Observer

public interface Observer {
    public abstract void update(NumberGenerator generator);
}

观察对象 NumberGenerator,用于生成数值的抽象类,里面保存了各种观察者observers,有增加和删除观察者的方法addObserver和deleteObserver,以及向所有观察者发送通知的方法notifyObservers。生成数值的方法execute和获取数值的方法getNumber是抽象方法,交由具体的观察对象去实现。

public abstract class NumberGenerator {
    private ArrayList observers = new ArrayList();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void deleteObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        Iterator it = observers.iterator();
        while (it.hasNext()) {
            Observer o = (Observer) it.next();
            o.update(this);
        }
    }

    public abstract int getNumber();
    public abstract void execute();
}

具体的观察对象 RandomNumberGenerator,它会生成随机数

public class RandomNumberGenerator extends NumberGenerator{

    private Random random = new Random();
    public int number;

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

    @Override
    public void execute() {
        for (int i = 0; i < 20; i++) {
            number = random.nextInt(50);
            notifyObservers();
        }
    }
}

具体的观察者 DigitObserver,实现了Observer接口,update方法是将传过来的观察对象,输出其生成的数值。(为了方便观察,使用Thread.sleep降低了程序的运行速度)

public class DigitObserver implements Observer {
    @Override
    public void update(NumberGenerator generator) {
        System.out.println("DigitObserver:" + generator.getNumber());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

具体的观察者 GraphObserver, 同样实现了Observer接口,update方法将观察对象生成的数值以***的形式显示。

public class GraphObserver implements Observer {
    @Override
    public void update(NumberGenerator generator) {
        System.out.print("GraphObserver:");
        for (int i = 0; i < generator.getNumber(); i++) {
            System.out.print("*");
        }
        System.out.println("");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试类

public class Main {
    public static void main(String[] args) {
        NumberGenerator generator = new RandomNumberGenerator();
        Observer observer1 = new DigitObserver();
        Observer observer2 = new GraphObserver();
        generator.addObserver(observer1);
        generator.addObserver(observer2);
        generator.execute();

    }
}

输出结果
在这里插入图片描述

注意的点

  1. 尽量不要在Observer中对观察对象进行修改操作,否则容易引发循环调用(即subject状态改变,通知observer,observer修改subject的状态,导致subject又触发通知observer,无限循环)。
  2. 为了保持各个Observer类的独立性,不能因为update方法的调用顺序发生改变而产生问题。
  3. 传递更新信息的方式,有三种,1是直接将观察对象作为update方法的参数给到observer;2是将观察对象和更新值同时作为参数;3是只传递更新值(这样subject里的依赖性很强,不好)
  4. 实际上Observer角色并非主动地去观察,而是被动地接受来自subject角色的通知,因此Observer模式也被称为Publish-Subscribe(发布-订阅)模式。

java.util.Observer接口

其实java类库中的java.util.Observer接口和java.util.Observable类提供了实现Observer模式的工具类,只是由于观察对象都需要继承Observable这个抽象类才可作为subject角色。但是java是单继承的,原先的观察对象可能已经是其他类的子类了,就没办法用这套工具类来实现Observer模式,所以被弃用了。

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值