关注我并转发此文,私信找我领取设计模式相关学习视频哦!!!!
好了废话不多说,咱们开撸观察者模式
定义
观察者三个字大家乍一听,最先想到的是什么,我最开始听到这三个字的时候,想到的是特务、监视、监听,哈哈,可能是谍战片看多了。我们可以把观察者当成中间第三者,负责收集消息和发布消息的人,比如:在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了,这个小伙伴我们就可以理解为观察者,他负责收集情报,并通知对这个情报感兴趣的其他小伙伴。
观察者模式其实也就是我们经常听到的一个词:发布订阅模式(模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式),相信用过redis的小伙伴,肯定知道这个词。其实主要思想就是:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
实现方式
下面我用一个通知工人消息的例子给大家具体演示一下,要实现观察者模式需要用的各种角色及实现的方法。
- a. 角色抽象类(提供对观察者的添加,删除和通知功能)
/**
* 角色抽象类
*
*/
public interface Watched {
public void addWatcher(Watcher watcher); //添加观察者(工人)
public void removeWarcher(Watcher watcher);//删除观察者(工人)
public void notifyWatcher(String str);//通知观察者(工人)
}
- b. 角色具体类,实现a,维护一个c的集合(对角色抽象类的实现)。
/**
* 角色实现类
*/
public class WatchedClass implements Watched {
//维护一个观察者(工人)的集合
private ArrayList<Watcher> wList = new ArrayList<Watcher>();
private ArrayList<WorkerWatcher> wList = new ArrayList<WorkerWatcher>();
@Override
public void addWatcher(WorkerWatcher workerWatcher) {
wList.add(workerWatcher);
}
@Override
public void removeWarcher(WorkerWatcher workerWatcher) {
wList.remove(workerWatcher);
}
@Override
public void notifyWatcher(String str) {
//遍历工人集合,将消息通知给每个工人
for (WorkerWatcher workerWatcher : wList) {
/*
此处只是个简单的示例,比如这可以根据我们工人的等级,收到不同的消息,
或者细化发送模型和工人模型完成我们想要达到的效果
*/
workerWatcher.updateSelf(str);
}
}
- c. 观察者抽象类(被角色通知后实现的方法,业就是工人的抽象模型)。
/**
* 观察者抽象接口,也就是工人的抽象
*/
public interface WorkerWatcher {
public void updateSelf(String str);
}
- d. 观察者实现类,实现c(多个),也就是实现多个工人模型。我这里实现2个,一个是车间主任,一个是普通工人。
/**
* 观察者实现类 车间主任
*/
public class Director implements WorkerWatcher {
private final static String MSG = "主任你好,您收到了最新消息:";
private String name;
public Director(String name) {
this.name = name;
}
@Override
public void updateSelf(String str) {
System.out.println(this.name MSG str);
}
}
/**
* 观察者实现类 普通工人
*/
public class WorkerClass implements WorkerWatcher {
private final static String MSG = " 您好,您收到了最新消息:";
private String name;
public WorkerClass(String name) {
this.name = name;
}
@Override
public void updateSelf(String str) {
System.out.println(this.name MSG str);
}
}
- 客户端
/**
* 观察者模式使用Demo
* 1:角色抽象类
* 2:角色实现类
* 3:观察者抽象类
* 4:观察者实现类,可以多个实现类,同时观察角色类,通知后完成不同的功能
* 具体就是角色类提供添加和删除观察者的方法,同时提供通知所有观察者的方法,
* 观察者类接收通知方法,执行操作
*/
public class Client {
public static void main(String[] args) {
WatchedClass people = new WatchedClass();
WorkerWatcher director = new Director("李小楠");
WorkerWatcher worker = new WorkerClass("胡小然");
people.addWatcher(director);
people.addWatcher(worker);
//通知所有的观察者我要下班啦
people.notifyWatcher("下班啦");
//将普通工人从通知列表移出
people.removeWarcher(worker);
//通知主任去聚餐
people.notifyWatcher("去聚餐");
}
}
执行结果如下图:
优缺点
优点:
- 观察者和被观察者是抽象耦合的,改变主题或观察者中的一方,另一方不会受到影响。
- 建立了一套触发机制,可以无限复用。
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果观察者和观察目标间有循环依赖,可能导致系统崩溃。
- 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的。
总结
- 观察者模式可以分为两种模型(推模型和拉模型)
- 推模型是假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
- 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。
- 其实jdk对观察者模式进行的实现(特殊说一下,在这么多设计模式中,jdk只对观察者模式进行了支持,当然我后面会更新的动态代理,就不算在支持列表里面了,后面会解释),下面我们用jdk提供的类来实现下我们上面的例子:
public class WorkerObservable {
/**
* JDK 支持的观察者模式使用Demo(所有的设计模式中,JDK只对观察者模式进行了支持,其他的都需自己设计)
* 和自己写的观察者模式基本相同,可以看下源码就理解啦 是个重要的模式哦
*/
public static void main(String[] args) {
obServableClass obServableClass = new obServableClass();
Observer Director1 = new Director1("胡小然");
Observer Worker1 = new Worker1("李小楠");
obServableClass.addObserver(Director1);
obServableClass.addObserver(Worker1);
obServableClass.run("下班了");
}
}
//就是上面的 角色实现类,Observable是jdk帮我们实现的通知类
class obServableClass extends Observable {
public void run(String str) {
this.setChanged();// 变更成chang状态
this.notifyObservers(str);
}
}
//具体的工人实现类,车间主任,Observer就是 角色抽象类
class Director1 implements Observer {
private final static String MSG = "主任你好,您收到了最新消息:";
private String name;
public Director1(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(this.name MSG arg);
}
}
//具体的工人实现类,普通工人
class Worker1 implements Observer {
private final static String MSG = " 您好,您收到了最新消息:";
private String name;
public Worker1(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(this.name MSG arg);
}
}
最后和每次一样,放张设计模式学习视频的截图,感兴趣的小伙伴,关注转发后私聊我获取哦