作者:云都小生
推荐资料:
史上最全设计模式导学目录
前奏
各位小伙伴们,请想像一下,生活中是否有一种对象,它在状态在改变之后,其他的对象就会做出某些响应。
以前很火的穿越火线,是一款第一视角的射击游戏,在游戏中,玩家可以进行组队的游戏。游戏为每个玩家提供了雷达,上面显示了各个队友的位置情况。一旦某个队友被射杀,其他各个玩家都可以从雷达上看到一个“X”的标记。
这个时候,如果你是设计者,会怎么完成这个功能呢?一般程序员会这么设计:
每个玩家都持有其他玩家的所有引用,一旦状态发生了任何改变,就向各个玩家发送消息,其他玩家各自做出响应,如图。
这样就会使各个对象之前的引用关系变得非常复杂,不利于代码的维护等,所以,我们可以考虑一下观察者模式。
概述
设计模式是使用最为频繁的行为型设计模式之一, 定义了对象之间的一种低耦合的依赖关系,并且使得每一个对象状态发生改变的时候,其他对象都会被通知并自动更新。
这个模式可以用来设计广播通信,一旦某个节点发生了状态的改变,就通知其他的节点。
观察者模式一般有以下几种角色:Subject(目标)、ConcreteSubject(具体目标)、Observer(观察者)、ConcreteObserver(具体观察者)。
目标:目标是被观察的对象,这个对象中定义了一个观察者的集合,用来动态的增加多个观察者。同时,还提供了一系列的方法来对观察者对象进行操作。当它自身内部有一些状态进行改变的时候,就会通知相对应的观察者。
具体目标:具体目标是目标类的子类,定义了具体的业务逻辑。
观察者:观察者收到通知后,会通知其他的目标类。
具体观察者:在具体观察者中,需要维持一个对具体目标对象的引用,收到通知后就向具体目标对象进行响应。
简单模板
//抽象观察者
import java.util.ArrayList;
abstract class Subject
{
//定义一个观察者集合用于存储所有观察者对象
protected ArrayList<Observer> observers = new ArrayList();
//用于向观察者集合中增加一个观察者
public void attach(Observer observer)
{
observers.add(observer);
}
//用于在观察者集合中删除一个观察者
public void detach(Observer observer)
{
observers.remove(observer);
}
//声明抽象通知方法
public abstract void notice();
}
//具体观察者
class ConcreteSubject extends Subject
{
//实现通知方法
public void notice()
{
//遍历观察者集合,调用每一个观察者的响应方法
for(Object obs : observers)
{
((Observer)obs).update();
}
}
}
//抽象目标类
interface Observer
{
//声明修改状态的方法
public void update();
}
//具体目标类
public class ConcreteObserver implements Observer {
//实现响应方法
public void update()
{
System.out.println("响应!");
}
}
//测试类
public class Test
{
public static void main(String[] args)
{
ConcreteObserver observer1 = new ConcreteObserver();
ConcreteObserver observer2 = new ConcreteObserver();
ConcreteObserver observer3 = new ConcreteObserver();
ConcreteSubject subject = new ConcreteSubject();
subject.attach(observer1);
subject.attach(observer2);
subject.attach(observer3);
subject.notice();
}
}
我看过网上的一些例子,观察者模式还可以别用来设计游戏中,盟友之间的相应。一旦盟友遭受攻击,其他盟友就会收到通知。
JDK支持
Java的util包中,提供了对观察者模式的支持——Observable类和Observer接口。
Observer接口,只声明了一个方法,它充当抽象观察者。
void update(Observable o, Object arg);
当观察目标的状态发生改变时,改方法就会被调用。
Observable,就是JDK提供的具体目标,这个目标类提供了一些关键的方法。
Observable() 构造方法 实例化存储观察者的向量
addObserver(Observer o) 增加一个观察者到向量中
deleteObserver(Observer o) 在向量中删除一个观察者对象
notifyObserver() 通知每一个观察者的update()方法
deleteObservers() 记住,这里结尾有个s,清空向量
总结
观察者模式提供了一种实现对象之间联动的解决方案,适用于一对多的对象交互场景。
优点:由于有了抽象层(观察者、目标类),建立了一个低耦合的关系,降低了复杂度和维护成本。符合“开闭”原则,可以随时增加观察者、目标类。
缺点:如果观察者目标对象太多,就会降低效率。
2018/3/13 20:00:57 @Author:Cloudking