设计模式之观察者模式

  • 定义
  • 类型
  • 类图
  • 结构
  • 有趣的例子

定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。


类型:行为类模式


类图:
这就是观察者模式类图


结构:在最基础的观察者模式中,包括以下四个角色:

  1. 被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
  2. 观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
  3. 具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
  4. 具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。

有趣的例子
1.假设我们有一情景是这样子的:小孩子在睡觉,醒来后爸爸要给孩子喂东西吃,爷爷要抱小孩子,叔叔要亲小孩子。
从情景中我们分析:首先孩子当前的状态是睡着的,爸爸,爷爷,叔叔都需要观察小孩子睡醒后才能进行一系列动作。那么我们很容易想到的就是在实现的时候将小孩子的类封装到爸爸,爷爷,和叔叔的类中,让爸爸,爷爷,叔叔去主动观察小孩子的状态。这是一种可行的方法,但是此方法需要不断的去监视小孩子的状态,导致爸爸,爷爷,叔叔在小孩子睡着的这段时间一直处于状态,这样是不是太累了。因此我们想到:将这些观察者的类封装到小孩子的类中,让小孩子主动醒来去通知观察者来执行相应的操作,这就是我们所要说的观察者模式。
那么接下来我们来实现这一情景需求:

Test.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;

class WakenUpEvent {
    private long time;
    private String location;
    private Child source;

    public WakenUpEvent(long time, String location, Child source) {
    super();
    this.time = time;
    this.location = location;
    this.source = source;
    }

    public long getTime() {
    return time;
    }

    public void setTime(long time) {
    this.time = time;
    }

    public String getLocation() {
    return location;
    }

    public void setLocation(String location) {
    this.location = location;
    }

    public Child getSource() {
    return source;
    }

    public void setSource(Child source) {
    this.source = source;
    }

}

class Child implements Runnable {
    private java.util.List<WakenUpListener> wakenUplisteners = new ArrayList<WakenUpListener>();

    public void addWakenUpListener(WakenUpListener l) {
    wakenUplisteners.add(l);
    }

    public void wakeUp() {
    for (int i = 0; i < wakenUplisteners.size(); i++) {
        WakenUpListener l = wakenUplisteners.get(i);
        l.ActionToWakenUp(new WakenUpEvent(System.currentTimeMillis(),
            "bed", this));
    }
    }

    @Override
    public void run() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    this.wakeUp();
    }

}

class Dad implements WakenUpListener {
    public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
    System.out.println("feed child");
    }
}

class GrandFather implements WakenUpListener {
    public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
    System.out.println("hug child");
    }
}

interface WakenUpListener {
    public void ActionToWakenUp(WakenUpEvent wakenUpEvent);
}

class PropertyMgr {
    private static Properties properties = new Properties();
    static {
    try {
        properties.load(Test.class.getClassLoader().getResourceAsStream(
            "zhaowanyue/observer.properties"));
    } catch (IOException e) {
        // TODO 自动生成的 catch 块
        e.printStackTrace();
    }
    }

    public static String getProperty(String key) {
    return properties.getProperty(key);
    }
}

public class Test {
    public static void main(String[] args) throws IOException {
    Child child = new Child();

    String[] observers = PropertyMgr.getProperty("observers").split(",");
    for (String s : observers) {
        try {
        child.addWakenUpListener((WakenUpListener) Class.forName(s)
            .newInstance());
        } catch (InstantiationException | IllegalAccessException
            | ClassNotFoundException e) {

        e.printStackTrace();
        }
    }
    new Thread(child).start();
    }
}
observer.properties
observers=zhaowanyue.Dad,zhaowanyue.GrandFather
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值