JAVA设计模式---观察者模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cheidou123/article/details/81038912

一、观察者模式

定义了对象一对多以来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

二、观察者模式的四个组成

1.被观察者接口

⑴registerObserver()

将观察者注册到被观察者中

⑵removeObserver()

将观察者移除

⑶notifyObserver()

被观察者状态发生改变时通知观察者

2.被观察者实现

实现接口方法,同时保存一个以观察者接口为泛型的list,这个list主要存放注册的观察者。

3.观察者接口

⑴update()

一旦被观察者通知观察者,调用update方法。

4.观察者实现

实现接口方法

三、我们自己写观察者的例子

⑴推模型

假设我们A,B,C三个人同时预定了一辆车,当我们车上市时我们就会把车是哪一款的,以及车的价格通知给他们。

/***
 * @author bincai
 * @email 1355869831@qq.com
 */
public class  ObserverPatternPush{
    public static void main(String[] args) {
        Car car = new Car();
        //创建三个不同的观察者
        Observer customerA = new Customer("A");
        Observer customerB = new Customer("B");
        Observer customerC = new Customer("C");

        //将观察者注册到被观察者中
        car.registerObserver(customerA);
        car.registerObserver(customerB);
        car.registerObserver(customerC);

        //更新被观察者中的数据,当数据更新后,会自动通知所有已注册的观察者
        car.setInfomation(5, 120000);

    }
}

//定义被观察者接口
interface UnderObserver {
    //注册观察者
    public void registerObserver(Observer o);
    //移除观察者
    public void removeObserver(Observer o);
    //将被观察者的变动通知观察者
    public void notifyObservers();
}

//定义观察者接口
interface Observer {
    //观察者接受通知执行,cost即车的价格
    public void update(int edition,float cost);
}

//定义被观察者实现类,这里的被观察者就是car
class Car implements UnderObserver {
    //定义一个集合,来存放观察者
    private List<Observer> mObservers;
    //车的款型
    private int edition;
    //车的价格
    private float cost;

    //构造函数
    public Car() {
        mObservers = new ArrayList<>();
    }

    //将观察者加入到集合中去
    @Override
    public void registerObserver(Observer o) {
        mObservers.add(o);
    }

    //将观察者从集合中移除
    @Override
    public void removeObserver(Observer o) {
        int i = mObservers.indexOf(o);
        if(i >= 0)
            mObservers.remove(i);
    }

    //通知观察者被观察者改变了
    @Override
    public void notifyObservers() {
        //遍历通知观察者
        for(int i = 0; i < mObservers.size(); i++){
            Observer observer = mObservers.get(i);
            observer.update(edition, cost);
        }
    }

    //这个操作完了之后,我们就要通知观察者
    public void setInfomation(int edition,float cost){
        this.edition = edition;
        this.cost = cost;
        //信息更新完毕,通知所有观察者
        notifyObservers();
    }

}

class Customer implements Observer {

    private String name;
    private int edition;
    private float cost;

    public Customer(String name){
        this.name = name;
    }

    //观察者被通知后触发
    @Override
    public void update(int edition, float cost) {
        this.edition = edition;
        this.cost = cost;
        buy();
    }

    public void buy(){
        System.out.println(name+"订阅的"+edition+"系车,价格是"+cost+"元。");
    }

}

输出:

A订阅的5系车,价格是120000.0元。
B订阅的5系车,价格是120000.0元。
C订阅的5系车,价格是120000.0元。

⑵拉模型

在上面的例子中,是被观察者通知观察者,是一种推模型方式,我们也可以把被观察者自身的引用传递给观察者,然后观察者通过get来获取相关信息,这就是拉模型

拉模型和推模型有三点不同:

⑴观察者接口update传入了被观察者的接口

⑵被观察者通知更新的时候会传入具体对象

⑶观察者update实现方法将被观察者接口转成具体的对象

/***
 * @author bincai
 * @email 1355869831@qq.com
 */
public class  ObserverPatternPull {
    public static void main(String[] args) {
        CarPull car = new CarPull();
        //创建三个不同的观察者
        ObserverPull customerA = new CustomerPull("A");
        ObserverPull customerB = new CustomerPull("B");
        ObserverPull customerC = new CustomerPull("C");

        //将观察者注册到被观察者中
        car.registerObserver(customerA);
        car.registerObserver(customerB);
        car.registerObserver(customerC);

        //更新被观察者中的数据,当数据更新后,会自动通知所有已注册的观察者
        car.setInfomation(5, 120000);

    }
}

//定义被观察者接口
interface UnderObserverPull {
    //注册观察者
    public void registerObserver(ObserverPull o);
    //移除观察者
    public void removeObserver(ObserverPull o);
    //将被观察者的变动通知观察者
    public void notifyObservers();
}

//定义观察者接口
interface ObserverPull {
    //观察者接受通知执行,cost即车的价格
    //拉模型和推模型区别1 这里传入的是被观察者的引用
    public void update(UnderObserverPull underObserverPull);
}

//定义被观察者实现类,这里的被观察者就是car
class CarPull implements UnderObserverPull {
    //定义一个集合,来存放观察者
    private List<ObserverPull> mObservers;
    //车的款型
    private int edition;
    //车的价格
    private float cost;

    //构造函数
    public CarPull() {
        mObservers = new ArrayList<>();
    }

    //将观察者加入到集合中去
    @Override
    public void registerObserver(ObserverPull o) {
        mObservers.add(o);
    }

    //将观察者从集合中移除
    @Override
    public void removeObserver(ObserverPull o) {
        int i = mObservers.indexOf(o);
        if(i >= 0)
            mObservers.remove(i);
    }

    //通知观察者被观察者改变了
    //拉模型和推模型区别2
    @Override
    public void notifyObservers() {
        //遍历通知观察者
        for(int i = 0; i < mObservers.size(); i++){
            ObserverPull observer = mObservers.get(i);
            observer.update(this);
        }
    }

    //这个操作完了之后,我们就要通知观察者
    public void setInfomation(int edition,float cost){
        this.edition = edition;
        this.cost = cost;
        //信息更新完毕,通知所有观察者
        notifyObservers();
    }

    //拉模式当然也要能访问到属性,这也勉强算个区别4
    public int getEdition() {
        return edition;
    }

    public void setEdition(int edition) {
        this.edition = edition;
    }

    public float getCost() {
        return cost;
    }

    public void setCost(float cost) {
        this.cost = cost;
    }
}

class CustomerPull implements ObserverPull {

    private String name;
    private int edition;
    private float cost;

    public CustomerPull(String name){
        this.name = name;
    }

    //观察者被通知后触发
    //拉模式和推模式的区别3
    @Override
    public void update(UnderObserverPull underObserverPull) {
        CarPull carPull = (CarPull)underObserverPull;
        this.edition = carPull.getEdition();
        this.cost = carPull.getCost();
        buy();
    }

    public void buy(){
        System.out.println(name+"订阅的"+edition+"系车,价格是"+cost+"元。");
    }

}

输出:

A订阅的5系车,价格是120000.0元。
B订阅的5系车,价格是120000.0元。
C订阅的5系车,价格是120000.0元。

四、Java内置观察者模式

在java的util库里,提供了一个类和一个接口来对观察者模式支持

①Observable类,被观察者继承

这个类里面setChanged()和notifyObservers()方法比较重要,其中setChanged方法用来设置一个标志位来标明数据发生了变化,notifyObservers()这个就不用说了

②一个Observer接口,观察者实现

里面就一个update方法,具体可以自己进去瞅瞅

我们来看一个实例,这个是采用拉模式的:

/***
 * @author bincai
 * @email 1355869831@qq.com
 */
public class  ObserverPatternInner {
    public static void main(String[] args) {
        //创建被观察者
        CarInner journal = new CarInner();
        //创建三个不同的观察者
        Consumer consumerA = new Consumer("A");
        Consumer consumerB = new Consumer("B");
        Consumer consumerC = new Consumer("C");
        //将观察者注册到被观察者中
        journal.addObserver(consumerA);
        journal.addObserver(consumerB);
        journal.addObserver(consumerC);
        //更新被观察者中的数据
        journal.setInfomation(6, 11);

    }
}

//被观察者实现了observable接口
class CarInner extends Observable {
    private int edition;
    private float cost;

    public void setInfomation(int edition,float cost){
        this.edition = edition;
        this.cost = cost;
        setChanged();
        //调用无参数的方法,使用拉模型,这里不用放参数,因为父类已经搞好了
        notifyObservers();
    }

    //提供get方法
    public int getEdition(){
        return edition;
    }

    public float getCost(){
        return cost;
    }
}

//观察者实现Observer接口
class Consumer implements Observer {

    private String name;
    private int edition;
    private float cost;

    public Consumer(String name){
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        //判断o是否是CarInner的一个实例
        if(o instanceof CarInner){
            //强制转化为CarInner类型
            CarInner c = (CarInner) o;
            //拉取数据
            this.edition = c.getEdition();
            this.cost = c.getCost();
            buy();
        }

    }

    public void buy(){
        System.out.println(name+"订阅了"+edition+"车,价格是"+cost+"元。");
    }

}

输出:


C订阅了6车,价格是11.0元。
B订阅了6车,价格是11.0元。
A订阅了6车,价格是11.0元。

 

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页