《一天一模式》— 观察者模式

1、观察者模式的概念

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知全部的观察者对象,使他们可以自动更新本身。 java

2、何时使用观察者模式

当一个对象被修改,或者发生某些变化时,须要自动通知依赖它的一些对象,则可使用观察者模式。编程

例如:当汽车熄火时,须要更新汽车的定位、发送熄火的通知、生成本次的行程,就可使用观察者模式,这个例子中发生变化的位置是熄火,那么发生熄火须要通知依赖它的一些对象,就是定位、通知和行程。spa

下面来看看,如何用Java语言实现观察者模式。设计

3、怎么使用观察者模式

3.1 不适用观察者模式的弊端

用上面说的业务场景为例,若是不使用观察者模式来实现,能够看下面的伪代码:code

public class EngineOffEvent() {

    public void engineOff() {
        Location localtion = new Localtion();
        Notification notification = new Notification();
        Trip trip = new Trip();

        localtion.update();
        notification.notify();
        trip.createTrip();
    }
}

这种作法有以下两个主要弊端:server

  • 耦合度高:能够看到EngineOffEvent类耦合了全部其余的业务类,形成维护困难;
  • 扩展性差:当须要在熄火时作新业务时,须要修改engineOff方法内的代码,违反了开闭原则;
  • 灵活度低:不能控制通知的对象个数;

3.2 如何用观察者模式解决问题

根据上面的需求,用观察者模式进行设计,下面看看类图和代码:对象

代码以下:blog

/**
 * 观察者接口。
 * */
public interface Observer {
    /**
     * 当气象监测数据改变时,主题会把这些状态值看成方法的参数,传送给观察者。
     * */
    void update(String data);
}

public class LocaltionObserver implements Observer{
    public void update(String data) {
        System.out.println(data + ":更新位置。");
    }
}

public class NotificationObserver implements Observer{
    public void update(String data) {
        System.out.println(data + ":发送通知。");
    }
}

public class TripObserver implements Observer {
    public void update(String data) {
        System.out.println(data + ":生成行程。");
    }
}

/**
 * 主题接口。
 * */
public interface Subject {
    /**
     * registerObserver和removeObserver方法都须要一个观察者做为变量,该观察者是用来注册或被删除的。
     * */
    void registerObserver(Observer ob);

    void removeObserver(Observer ob);

    /**
     * 当主题的状态改变时,这个方法会被调用,已通知全部的观察者。
     * */
    void notifyObservers(String data);

}

// 熄火事件
public class EngineOffEvent implements Subject {

    // 观察者对象集合
    private List<Observer> observers;

    public EngineOffEvent() {
        observers = new ArrayList<Observer>();
    }

    // 注册观察者
    public void registerObserver(Observer ob) {
        observers.add(ob);
    }

    // 移除观察者
    public void removeObserver(Observer ob) {
        int index = observers.indexOf(ob);
        if (index >= 0)
            observers.remove(index);
    }

    // 发生变化进行通知
    public void notifyObservers(String data) {
        // 通知所有观察者
        for (Observer ob : observers) {
            ob.update(data);
        }
    }

}

// 使用
public class Client {

    public static void main(String[] args) {
        Subject subject = new EngineOffEvent();
        subject.registerObserver(new LocaltionObserver());
        subject.registerObserver(new NotificationObserver());
        subject.registerObserver(new TripObserver());
        subject.notifyObservers("京A88888熄火");
    }

}

//京A88888熄火:更新位置。
//京A88888熄火:发送通知。
//京A88888熄火:生成行程。

观察者模式主要分为两部分:继承

  • Subject,主题,是发生变化的那个对象,例子中是熄火事件;
  • Observer,观察者,是发生变化后须要通知的多个对象,例子中是通知、位置和行程;

在使用时,能够动态添加或者删除观察者,灵活配置。接口

3.3 观察者模式的好处

  • 耦合度低:解除了3.1小节中,EngineOffEvent类与其余的业务类的耦合;
  • 扩展性高:当须要在熄火时作新业务时,建立一个新对象实现Observer,而后注册到Subject便可;
  • 灵活度高:能够随意添加或移除Observer;

3.4 其余能够注意的地方

Java内置了观察者模式:

  • java.util.Observable(类)

  • java.util.Observer(接口)

可使用内置的观察者,可是其中Observable对应的是上面例子中的Subject,他是一个Class而不是Interface,若是使用内置的接口,则须要把宝贵继承机会用掉,若你的类已经使用了继承关系,则没法使用。

4、总结

上面的观察者模式,从代码上来讲,就是面相接口编程,在Subject中有一个List<Observer>,在发生变化后,循环调用List中的对象的方法,确保都通知到,而且能够对List进行添加和删除。

从业务上来讲,当发生某个事件后,须要批量通知许多个对象。则可使用这个模式。

以上就是我对观察者模式的一些理解,有不足之处请你们指出,谢谢。

相关文章
相关标签/搜索