设计模式学习笔记十一:观察者模式

设计模式学习笔记十一:观察者模式

介绍

观察者(observer)模式也叫发布-订阅模式,实现了观察者和被观察者的解耦操作,观察者可以根据自身需求选择关注哪些主题和取消关注哪些主题,当主题发生变化的时候会轮询通知观察者,所以主题和观察者之间是一对多的关系。

典型应用

  • MQ
  • AWT事件监听
  • NIO多路复用
  • ……

UML结构图:

observer

代码实现:

1.主题接口

package com.array7.observer;

public interface Subject<T> {
    /**
     * 创建观察者
     * @param observer
     */
    public void add(Observer<T> observer);

    /**
     * 删除观察者
     * @param observer
     */
    public void remove(Observer<T> observer);

    /**
     * 轮询通知观察或者
     */
    public void notifyObservers();
}

2.具体主题实现

package com.array7.observer;

import java.util.HashSet;
import java.util.Set;

/**
 * 具体的主题,即被观察者
 */
public class ConcrectSubject implements Subject<String> {
    private Set<Observer<String>> observers;

    private String changeData;

    public ConcrectSubject() {
        observers = new HashSet<Observer<String>>();
    }

    @Override
    public void add(Observer<String> observer) {
        observers.add(observer);
    }

    @Override
    public void remove(Observer<String> observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer<String> observer : observers) {
            observer.update(this.getChangeData());
        }
    }

    public String getChangeData() {
        return changeData;
    }

    /**
     * 触发update操作的方法
     */
    public void setChangeData(String changeData) {
        this.changeData = changeData;
        notifyObservers();
    }

}

3.观察者接口

package com.array7.observer;

/**
 * 观察者接口
 * @param <T>
 */
public interface Observer<T> {
    /**
     * 状态更新通知
     * @param t
     */
    public void update(T t);

    /**
     * 主题已经存在了一个remove(..)方法,依然可以提供一个取消订阅的方法(可选)
     * 为了区分这里名称定义为了quit()
     */
    public void quit();
}

4.具体观察者实现

package com.array7.observer;

/**
 * 具体的观察者
 */
public class ConcrectObserver implements Observer<String>, BizService<String> {
    private Subject<String> subject;

    public ConcrectObserver(Subject<String> subject) {
        subject.add(this);
        this.subject = subject;
    }

    @Override
    public void update(String str) {
        // logic
        dosmth(str);
    }

    @Override
    public void dosmth(String str) {
        System.out.println(Thread.currentThread().getName() + ":" + str);
    }

    @Override
    public void quit() {
        subject.remove(this);
    }
}

5.其他业务逻辑组合

package com.array7.observer;
/**
 * 强制在观察者具体实现类实现此方法
 */
public interface BizService<T> {
    public void dosmth(T t);
}

6.Run

package com.array7.observer;

/**
 * 运行类
 */
public class Run {
    public static void main(String[] args) {
        ConcrectSubject subject = new ConcrectSubject();
        // 初始化一个观察者
        new ConcrectObserver(subject);
        subject.setChangeData("abcd");
        subject.setChangeData("1234");

        ConcrectObserver tmpObserver = new ConcrectObserver(subject);
        subject.setChangeData("dcba");
        // 删除这个观察者
        subject.remove(tmpObserver);

        // 新加入的观察者,我们预计会输出两次4321 :]
        new ConcrectObserver(subject);
        subject.setChangeData("4321");
    }
}

TIPS

在JDK中也提供的观察者模式的实现,但是JDK中的观察者接口是使用抽象类实现的。这就意味着如果想使用JDK中自带的实现,就不能再继承其他的基类了。而如果在基类继承,代码耦合度又会上来,因为可能不是所有的类都需要使用观察者。能用接口,尽量不用继承,也是设计原则之一:多用组合,少用继承

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-07-27 08:54  土豆条  阅读(191)  评论(0编辑  收藏  举报