转载:Java设计模式(四) 观察者模式

观察者模式

定义

观察者模式又叫发布-订阅模式,它定义了一种一对多的依赖关系,多个观察者对象可同时监听某一主题对象,当该主题对象状态发生变化时,相应的所有观察者对象都可收到通知。

 

针对接口编程,不针对实现编程,为交互对象之间的松耦合设计而努力。

UML

 观察者模式具体划分

  • 主题,抽象类或接口,如上面类图中的AbstractSubject
  • 具体主题,如上面类图中的Subject1,Subject2
  • 观察者,如上面类图中的IObserver
  • 具体观察者,如上面类图中的Observer1,Observer2,Observer3

实例

猎头或者HR往往会有很多职位信息,求职者可以在猎头或者HR那里注册,当猎头或者HR有新的岗位信息时,即会通知这些注册过的求职者。这是一个典型的观察者模式使用场景。

/**

 *观察者订阅的主题

 */

public interface Subject {

    public void addObserver(Observer observer);

    

    public void deleteObserver(Observer observer);

    

    public void notifyAllObserver();

}

/**

 * 主题实现类

 */

public class SubjectAchieve implements Subject {

    private List<Observer> observerList;

    private boolean changed = false;//主要用于控制订阅发布的粒度控制

    private User user;

    

    public SubjectAchieve() {

        observerList = new ArrayList<Observer>();

    }

    

    @Override

    public void addObserver(Observer observer) {

        observerList.add(observer);

    }

 

    @Override

    public void deleteObserver(Observer observer) {

        observerList.remove(observer);

    }

 

    @Override

    public void notifyAllObserver() {

        if (changed) {

            for (Observer observer : observerList) {

                observer.update(user);

            }

            changed = false;

        }

    }

    

    public void setUser(User user) {

        this.user = user;

    }

    

    public void setChanged(boolean changed) {

        this.changed = changed;

    }

}

//观察者接口

public interface Observer {

    public void update(User user);

}

//观察者实现类

public class ObserverAchieve implements Observer {

    private Subject subject;

    

    public ObserverAchieve(Subject subject) {

        this.subject = subject;

        subject.addObserver(this);

    }

    

    @Override

    public void update(User user) {

        System.out.println("age:" + user.getAge() + "\tname:" + user.getName());

    }

}

//又一观察者实现类

public class ObserverAcnieveOther implements Observer {

    private Subject subject;

    

    public ObserverAcnieveOther(Subject subject) {

        this.subject = subject;

        subject.addObserver(this);

    }

    

    @Override

    public void update(User user) {

        System.out.println("ageOther:" + user.getAge() + "\tnameOther:" + user.getName());

    }

}

/**

 * 主题将此的变化通知给观察者

 */

public class User {

    private int age;

    private String name;

    public User() {}

    public User(int age, String name) {

        this.age = age;

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

}

//测试类

public class Test {

    public static void main(String[] args) {

        SubjectAchieve subject = new SubjectAchieve();

        Observer observer = new ObserverAchieve(subject);

        

        Observer observer1 = new ObserverAcnieveOther(subject);

        

        subject.setChanged(true);

        

        User user = new User(12, "xxx");

        subject.setUser(user);

        

        subject.notifyAllObserver();

   }

}

//结果:

age:12 name:xxx

ageOther:12 nameOther:xxx
View Code

 

优点

  • 抽象主题只依赖于抽象观察者
  • 观察者模式支持广播通信
  • 观察者模式使信息产生层和响应层分离

缺点

  • 如一个主题被大量观察者注册,则通知所有观察者会花费较高代价
  • 如果某些观察者的响应方法被阻塞,整个通知过程即被阻塞,其它观察者不能及时被通知

spring中用例(ApplicationEventApplicationListener)

例如:spring事件驱动模型--观察者模式在spring中的应用

posted on 2016-08-19 11:16  反光的小鱼儿  阅读(188)  评论(0编辑  收藏  举报