四、观察者模式

什么是观察者模式?

       当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

应用场景:

         一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

解释说明:

         1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。

何时使用(一对多):  

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

上代码(下图是代码架构):

                               

代码:

这个是抽象类Observer:

// Observer抽象类,扩展了实体Observer的实体类
public abstract class Observer {
    // 把一个类放进抽象类中意义:其实与普通类中放进去道理一样
    public Subject subject;
    // 定义抽象类,由实现类实现
    public abstract void update();
}

下面这个是subject类:发布者与观察者之间的桥梁

public class Subject {
    
    private List<Observer> observers = new ArrayList<Observer>();
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        // 通知所有的观察者,调用notifyall()方法
        notifyAllObservers();
    }

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

    public void notifyAllObservers() {
        for (Observer observer : observers) {
            // 更新每一个观察者查看的信息
            observer.update();
        }
    }
}

下面这个是观察者(1):

public class OctalObserver extends Observer {

    public OctalObserver(Subject subject) {
        this.subject = subject;
        this.subject.add(this);
    }

    @Override
    public void update() {
        System.out.println("Octal String: "
                + Integer.toOctalString(subject.getState()));
    }
}

下面这个是观察者(2):

public class HexaObserver extends Observer {

    public HexaObserver(Subject subject) {
        this.subject = subject;
        this.subject.add(this);
    }

    @Override
    public void update() {
        System.out.println("Hex String: "
                + Integer.toHexString(subject.getState()).toUpperCase());
    }
}

接下来是发布者:

public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        new HexaObserver(subject);
        new OctalObserver(subject);
        new BinaryObserver(subject);

        System.out.println("First state change: 15");
        subject.setState(15);
        System.out.println("Second state change: 10");
        subject.setState(10);
    }
}

知识点总结:

       其实在观察者模式中,主要采用的技术也就是利用抽象类去实现的Java类的扩展;

抽象类特点

(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写; 

(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样; 

(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。

注意:虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。

还有值得庆幸的是,Java API 有内置的观察者模式:Java util package 包含最基本的Oberver 和Observerable 类,它们两个之间的关系就是Subject与Observer接口类似。并且许多功能都已经实现好了,我们只需要 push 和 pull 就行了;

经验吸取:

 在我们拉数据之前,我们可以设置一个"setChanged()"方法,好让notifyObservers()知道它被调用时应该更新观察者,如果调用notifyObsservers()之前,首先调用setChanged()方法,观察就不会被通知,让我们看看setChanged()方法,

其实对于Java.util.Observable 提供的,这个也有弊端:

(1)它是一个类,并不是一个接口,更糟糕的是,它没有试下你一个接口,限制了它的很多复用,必须设计一个类去继承它,如果某类想要多也想继承它,就陷入了两难的境地,因为Java不支持多重继承的能力;

(2)还有就是ObsercableAPI,setChanged()方法已经被保护起来了,被定义成了Protected:除非你继承它,否则你是五发封装组合到自己的对象中来,这个设计就违反了第二个原则:“多用组合,少用继承”。

发布了241 篇原创文章 · 获赞 31 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_40406929/article/details/102958637